36

Before are all you burn me alive, I must say that I have googling this question many times and I still can't understand the difference between List<Object> and List<?>

All books I've read say that in Java every class is implicitly a subclass of Object.

However I saw here the follwing code:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

This code is wrong (intentionally for educational purposes) and according to the author the reason is:

[...] prints only a list of Object instances; it cannot print List<Integer>, List<String>, List<Double>, and so on, because they are not subtypes of List<Object>

The solution is:

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

As you can see, the only difference is the first line:

public static void printList(List<Object> list) {
public static void printList(List<?> list) {

This is the reason of my question: What's the difference between List<Object> and List<?> ?

After all is Object superclass of everything or not?

If someone can help me with a simple explanation (I'm new with Java) I'll appreciate.

Thank you in advance.


Problems using member function as custom deleter with std::shared_ptr

I'm trying to work out how to use std::shared_ptr with a custom deleter. Specifically, I'm using it with SDL_Surface as:

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....),SDL_FreeSurface);

which compiles and runs fine. However, I would like to try out my own deleter and cannot work out how to do so. The documentation for SDL_FreeSurface is found here:

http://sdl.beuc.net/sdl.wiki/SDL_FreeSurface

in which I find the SDL_FreeSurface is declared as:

void SDL_FreeSurface(SDL_Surface* surface);

As a test, and going by that information, I tried the following function:

void DeleteSurface(SDL_Surface* surface)
{
    std::cout << "Deleting surface\n";
    SDL_FreeSurface(surface);
}

However, compiling with g++ gives me the following error:

error: no matching function for call to 'std::shared_ptr<SDL_Surface>::shared_ptr(SDL_Surface*, <unresolved overloaded function type>)'

I have looked at the gnu documentation for the gcc std::shared_ptr implementation but cannot make much sense of it. What am I doing wrong?

EDIT: I've since narrowed down the problem, but will leave the original question above. What I had was a Game class which, if I strip it down to a basic implementation, was something like:

class Game {
    public:
        /* various functions */
    private:
        void DeleteSurface(SDL_Surface* surface);
        bool CacheImages();
        std::vector<std::shared_ptr<SDL_Surface> > mCachedImages;

        /* various member variables and other functions */
}

with the implementation of DeleteSurface as above, and the implementation of CacheImages() as:

bool CacheImages()
{
    mCachedImages.push_back(std::shared_ptr<SDL_Surface>(SDL_LoadBMP(...),DeleteSurface);
    return true;
}

which game me the error I listed above. However, if I move the DeleteSurface() function outside the Game class without otherwise altering it, the code compiles. What is it about including the DeleteSurface function in the Game class that is causing problems?

4

7 に答える 7

25

説明:

? 「ワイルドカード」です。さまざまな方法で使用できます。

無制限のワイルドカード:

? 

上限のあるワイルドカード:

? extends Object (or another class)

下限のあるワイルドカード

? super Object (or another class)

例:

List <?> list;

list任意の型パラメーターを使用して、任意のリストに割り当てることができます。

List<? extends Number> list;

型パラメーター Number (または Integer、Float、ecc) を持つ任意の List をリストに割り当てることができます。

List<? super Integer> list;

型パラメーター Integer、または Integer(Number,Comparable, Serializable, Object ...) の型 gerarchy 内の型を持つ任意の List をリストに割り当てることができます。

概要:

だから宣言

List<Object> list;

と類似しています

List<? super Object> list;

オブジェクトのリストのみを「リスト」に割り当てることができるため。次に、この方法でリストを使用できます。

    list = new ArrayList<Object>();
    list.add(new String(""));
    list.add(new Integer(3));
于 2012-09-09T17:28:55.150 に答える
9

主な違いの 1 つは、リストを変更する方法です。以下はうまくいきます

List<Object> l1;
l1.add(new Object()); // OK

2 番目のケースではコンパイル エラーが発生します。

List<?> l2;
l2.add(new Object()); // Compile error

その理由は、サイトですでに数回議論されていると思います。要するに、( 1 のように)特定未知の型を<?>意味します。その型はコンパイル時に認識されないため、リストを変更することはできません。

于 2012-09-09T16:40:37.173 に答える
8

それStringが のサブタイプであることは、 が のサブタイプであるObjectことを意味しません。その場合、次のコードがコンパイルされます。List<String>List<Object>

List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
objects.add((Integer) 1);
strings.get(0).charAt(0); // but the Integer 1 does not have a charAt method ...

したがって、List<String>は のサブタイプではありませんList<Object>

List<String>とはどちらList<Object>も のサブタイプですList<?>。しかし、List<?>はより一般的な型であるため、 add メソッドが取る型を知ることはできません:

List<String> strings = new ArrayList<String>();
List<?> objects = strings;
objects.add((Integer) 1); // does not compile
于 2012-09-09T16:46:20.497 に答える
2

Object は String のスーパークラスですが、List<Object> は List<String> のスーパークラスではありません。もしそうなら、これは問題になるでしょう:

List<String> strings = ...
addObject(strings);
...
void addObjects(List<Object> objects) {
    objects.add(new Object());
}

現在、文字列には文字列ではない要素が含まれています。

于 2012-09-09T16:51:03.977 に答える
2

基本的に、両方のバージョンを同様の方法で使用できます。ただし、大きな違いが 1 つあります。次のことを宣言しましょう。

List<Object> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<String>();

それでは、以下のコードを試してみましょう。

list1.add("");// this works fine
list2.add("");// this one issues a compile error

誰かがこの理由を尋ねることができます。これはList<Object>、 ではコードがObject、またはサブタイプがあるList<?>ことを示しているためです。誰かがStringorDoubleを追加してから、 を読み取ってキャストしようとする可能性がありIntegerます。しかし、繰り返しますが、それは不可能です。

私が今覚えていない他の違いがあるかもしれません。

于 2012-09-09T16:43:26.767 に答える
2

このコードは (意図的に教育目的で) 間違っており、作者によるとその理由は次のとおりです。

[...] Object インスタンスのリストのみを出力します。List、List、List などは List のサブタイプではないため、出力できません。

これは、パラメーター化された型が不変であるためです。たとえば、クラス X および YList<X>は、 のサブタイプでもスーパータイプでもないためですList<Y>

違いは、無制限のワイルドカード タイプ ?は、タイプが不明であり、それについて何も推測できないことを意味するという点にあります。AList<?>はタイプ セーフです。A 以外の要素を配置することnullはできず、含まれるオブジェクトのタイプについて何も想定できません。

List<Object>明らかに、リストには任意のタイプのオブジェクトを含めることができることを意味します。

于 2012-09-09T17:50:31.450 に答える