9

doc about Wildcards in generics Оракул говорит,Почему я не могу использовать подстановочный знак (?) Как тип параметра, поле, локальную переменную или как тип возвращаемого метода?

Подстановочный может быть использован в различных ситуациях: как типа параметра, поле или локальной переменной; иногда как тип возврата (хотя это более конкретная практика программирования).

Я пробовал все четыре в следующем классе и получил ошибки компилятора на каждом из них. Зачем? Что я делаю не так?

public class MainClass { 
    private ? instanceFieldWithWildCardType;//ERROR 
    private static ? staticFieldWithWildCardType;//ERROR 

    private void methodWithWildCardParam(? param) {}//ERROR 

    private void methodWithWildCardLocalVariable() { 
     ? localVariableWithWildCardType;//ERROR 
    } 

    private ? methodWithWildCardReturnType() {//ERROR 
     return null; 
    } 

    private void methodWithWildCardParam(? param) {}//ERROR 

} 
+1

Поскольку это недопустимый синтаксис. Я не вижу никаких дженериков, просто '. –

+0

Лучше прочитать подразделы (https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html) подстановочных знаков в общей главе. Вы не можете использовать подстановочные знаки непосредственно для замены типов. Также см. Много примеров, представленных различными источниками в Интернете. –

ответ

5

Учебник очень сформулированного. Вы не можете использовать подстановочный знак для любой из перечисленных вещей. Вы можете использовать общий тип с шаблоном в нем для этих вещей.

public class Example { 
    ? field1;  // invalid 
    List<?> field2; // valid 

    private ? method1(? param) {return param;}    // invalid 
    private List<?> method2(List<?> param) {return param;} // valid 

    private void method3() { 
     ? var1;  // invalid 
     List<?> var2; // valid 
    } 
} 
8

? характер является wildcard type argument.

Статья начинается с

В родовом коде, знак вопроса (?), Называемый групповой символ, представляет собой неизвестный тип.

Единственное место, где вы можете использовать этот синтаксис, является частью общего кода, т.е. аргумент общего типа. Следующее предложение относится к универсальному коду с использованием шаблона. Так, например

как тип параметра

вы могли бы

public static void shuffle(List<?> list) { 

Или для

в качестве локальной переменной

public void method() { 
    List<?> list = Arrays.asList(1, 2, 3); 
    Collections.shuffle(list); 
    System.out.println(list); 
} 

Но

Подстановочного никогда не используются в качестве аргумента типа для универсального метода вызова, создания общего экземпляра класса, или надтипа.

Вы не можете использовать его как

Arrays.<?>asList(1, "", '5'); 
List<?> list = new ArrayList<?>(); 
... 
public class MyList implements List<?> {/* whatever */} 
+0

Также стоит отметить, что тот же самый код в последнем фрагменте был бы действительным, если бы он использовал 'T' вместо'? 'Для его ввода –

+0

Во всех этих примерах'? 'Не используется как тип, а скорее' List 'используется как тип. '?' отличается от 'List '. Я смущен: s – Solace

+1

@Solace '?' - это аргумент типа подстановки (http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1). Он не может использоваться вне контекста общих типов. –

2

Джокер может быть использован с <> оператор в концепции дженерик введенной в Java 5, используется для представления неизвестного типа. Generics используется для определения класса с членом в обобщенном формате. Если вы хотите предоставить объект, который при создании объекта пользователь будет указывать тип члена, тогда вы можете использовать концепцию дженериков. Он может использоваться только для того, чтобы член экземпляра не мог использоваться со статическими причинами. Память для статического элемента будет выделена только один раз.

Подстановочная концепция, введенная в дженериках для ограничения типа unknow, допустим, у меня есть список, который имеет подстановочный знак, и этот подстановочный знак расширяет класс обертки Number. Это означает, что список может работать с Integer, Long, Short, Byte, потому что они расширяют класс обертки Number, но не с String, поскольку класс String не расширяет класс обертки Number.

List<? extends Number> lt = new ArrayList<>(); 

приходит к вам программу, вы использовали неправильный синтаксис, как я уже упоминал подстановочные можно использовать с <> оператора.

Мы не использовать подстановочные в то время как инстанцировании класс, как упомянуто ниже -

List<?> lt = new ArrayList<?>(); 

но мы можем использовать дженерики, чтобы обеспечить поле, как неизвестный тип, как я, N, S в сотрудника класс. Это тип мы будем предоставлять при создании объекта класса -

class Employee<I,N,S> 
{ 
    I eid; 
    N empName; 
    S empSalary; 
} 

class Name 
{ 
    String firstName; 
    String middleName; 
    String lastName; 
} 

class salary 
{ 
    double basic; 
    float it; 
    float tds; 
    double netsal; 
} 

class CustomId 
{ 
    int empId; 
    String department; 
    int branchId; 
} 

main method 
------------ 

    Employee<Integer,String,Double> emp = new Employee<>(); 
    Employee<String,Name,Salary> emp2 = new Employee<>(); 
    Employee<CustomId,String,Salary> emp3 = new Employee<>(); 

Wildcard в качестве параметра метода -

public void sortList(List<?> lt) 
{ 
    // code to sort the list whether it is integer, String etc 
} 
call sortList() method 
----------------------- 
List<String> lt = new List<>(); 
lt.add("sss"); 
lt.add("aaa"); 
sortList(lt); 

List<Integer> lt = new List<>(); 
lt.add(11); 
lt.add(12); 
sortList(lt); 

объявляя локальную переменную в качестве шаблона -

List<?> lt = new ArayList<String>(); 
List<?> lt = new ArayList<Integer>(); 

Мы можем использовать подстановочные знаки и дженерики в качестве возвращаемого типа метода. Вот пример воспроизведенных в качестве возвращаемого типа метода -

public T getName(ClassName obj, Key key) 
{ 
    return (Type<T>)obj.getType(Key); 
} 

Вот пример шаблона в качестве возвращаемого типа метода -

List<?> method(List<?> data) 
    { 
     return data;  
    } 
+0

Ваш последний пример, вы можете показать использование wild card. –

+0

обновил мой ответ. – RCS

1

Подстановочные знаки не имеют индивидуального существования. Они всегда используются как параметр типа Generic classes Ex: List<? extends Number>. Я приведу один пример, охватывающий все сценарии.

import java.util.ArrayList; 
import java.util.List; 

class A{ 

    // I have not make use of this anywhere in this example 
    List<? extends Number> l1; //Field; 

    //Just taking l2 as parameter 
    //Wont be using it also 
    //Just tp show wildcard with generic as parameter 
    public List<? extends Number> operate(List<? extends Number> l2){ //As return Type; Not recommended Approach 

     List<Integer> list = new ArrayList<>(); 
     list.add(new Integer(6)); 
     return list; 
    } 

} 



public class Main { 

    public static void main(String[] args) { 

     List<? extends Number> ar = new ArrayList<Integer>(); //Local Variable 
     A obj = new A(); 
     System.out.println(obj.operate(ar)); 
    } 
}