精华内容
参与话题
问答
  • Generics

    2020-12-31 02:14:34
    <div><h1>Generics Proposal <h2>Motivations <p>The main reason for generics is to allow container types to be used by any type, yet type safe. This will be especially helpful for structures such as ...
  • GENERICS

    2011-12-12 20:52:44
    package genericAndCollection; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class TestGenerics {    static class Fruit{} ... static class Apple extends Fr
     
    

    package genericAndCollection;

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

    public class TestGenerics {
     
     static class Fruit{}
     
     static class Apple extends Fruit{}
     
     static class Orange extends Fruit{}
     
     public static void main(String[] args) {
      //1: the difference between ? and T
      //?: means that any number of non-determined class type, it represents N
      //T: means that one non-determined class type, it represents one
      
      //2: generics are not implementing polymorphism 
      List<Fruit> list = new ArrayList<Apple>();
      
      //3:static type or apparent type can not write while using the extends
      //to determine the type edge (downwards)
      List<? extends Fruit> list1 = new ArrayList<Apple>();
      list1.add(null);//otherwise will get compilation error
      //3.1: correct way
      List<Apple> list111 = new ArrayList<Apple>();
      list111.add(new Apple());
      List<? extends Fruit> list11 = list111;
      for(Fruit f: list11){}//to do}--read only
      
      //4: static type or apparent type can not read while using the super
      // to determine the type edge (upwards)
      //here, Gabriel said we can not get(compilation error) is wrong, it can not
      //use get due to no element there
      List<? super Fruit> list2 = new ArrayList<Fruit>();
      list2.get(0);
      //4.1: correct way
      List<Fruit> list22 = new ArrayList<Fruit>();
      list22.add(new Fruit());
      List<? super Fruit> list222 = list22;
      list222.get(0);
      
      //5: the actual type can not use ?, because jvm will have to know which
      //actual type initiated, here ? extends Fruit is any number of type possible
      //edge to Fruit
      List<? extends Fruit> list3 = new ArrayList<? extends Fruit>();
      
      //6: Array with generics, it has been implemented Polymorphism
      Fruit[] fruit = new Apple[5];
      fruit[0] = new Apple();//no error here, because while it runs, javap shows
              //anewarray command in bytecode, it doesn't actually init
                             //the instance of Fruit and Apple, it uses type [Fruit
      
      //7: force to cast while traverse using iterator
      List<Fruit> list7 = new ArrayList<Fruit>();
      //it records the actual types to meta data which located in signature
      //if in method parameter
      list7.add(new Apple());
      list7.add(new Orange());
      Iterator it = list7.iterator();
      while(it.hasNext()){
       System.out.println(it.next());
      }
      //7.1: try this--it shows if no generics here, any type can be added to this list
      //and it won't be forced to cast to Fruit, because it really didn't erase type
      List list77 = new ArrayList();
      list77.add(new Object());
      list77.add(new Orange());
      Iterator it1 = list77.iterator();
      while(it1.hasNext()){
       System.out.println((Apple)it1.next());//please do not froce it to cast
                  //will have java.lang.ClassCastException
      }
     }
    }

    展开全文
  • Java - Generics are not real generics

    万次阅读 2019-10-15 15:36:47
    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!...Java 5 added generics into the language. This allowed programmers to specify class types as parameters to other classes and m...

    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net

    Java 5 added generics into the language. This allowed programmers to specify class types as parameters to other classes and maintain type safety. For instance Set<Integer> is a set of integers and if you try to add a non-integer to it, a compile time error should occur.

    Java had been around a while by the time generics were added. Unfortunately it was considered too hard to add generics to the Java bytecode that forms a running Java program. Instead generics are just syntactic sugar. When a Java program is compiled the generics are checked, but after that they are stripped out. The bytecode that is run does not know anything about generics. This means it is possible to violate the generics constraints in the code at run-time (because the constraints don’t exist at run-time).

    Below is an example demonstrating the problem. A set of integers is created, but then using reflection a string is added to the set. This is clearly a violation of the set’s definition. However, reflection is a run-time process and the compiler is not smart enough to detect the potential error at compile-time (which would be very hard to do). If the set is now inspected (and not checked carefully), it will look like the integer 1 is in the set, rather than the actual string “1”. At this point various errors can occur, from the subtle contains error below, to outright ClassCastException if elements are extracted from the set as integers. As an aside, reflection is very cool and a great tool, but from my experience, most of the time it is the wrong tool.

    Set<Integer> integerSet = new HashSet<Integer>();
    Method addMethod = integerSet.getClass().getMethod("add", Object.class);
    addMethod.invoke(integerSet, "1");
    integerSet.contains(1); // -> false

    Remember, Java generics are not real generics. In particular pay special attention to using reflection on generic objects.

    展开全文
  • Const generics

    2020-12-27 21:14:46
    <div><p>Const generics are getting more popular. I can try to implement <code>heapless</code> using const generics and push it into a separate branch until they are stable. It is a nice challenge both...
  • Use generics

    2020-11-22 16:52:10
    generics. The code base already uses generics but very sparsingly. <p>Due to the design of Java generics and type erasure this should all be backwards compatible.</p><p>该提问来源于开源项目:...
  • RACSubject generics

    2020-12-08 18:55:41
    <div><p>Lightweight generics for RACSubject, giving us some autocompletion and helping us bridge with Swift. <p>Solves #58. <p>Unfortunately I couldn't find a nice way of extending the generics to...
  • Go Generics

    2021-01-08 14:21:07
    <div><p>Ever since the release of the go2go tool which allows for the usage of generics in Golang, you haven't included it in your great and awesome book "Go101". I think I speak for some ...
  • real generics

    2020-12-08 22:19:28
    1. real generics e.g 1-parametric or n-parametric polymorphism for functions 2. fake generics implementing by breaking the silly go type system https://github.com/gomacro/top for example your Where ...
  • Parse generics

    2020-12-30 06:14:59
    <div><p>This pull request is for parsing generics in the library macro. I tried to limit the scope, but it turned out a bit more comprehensive than anticipated. There are still some rough corners here...
  • Implementing Generics

    2020-12-02 04:49:19
    <div><p>I have been studying how generics work and I think I have come up with a solution that works just like the CLR runtime. <p>Every time a generic is used we duplicate the entire tree and ...
  • Concrete Generics

    2020-12-26 04:31:01
    s support for concretized generics. The main change is adding generic type argument substitution to various objects in the reflection model, as well as exposing concretized members (fields, methods, ....
  • generics support

    2020-12-25 21:56:21
    <div><p>Is there a chance generics will eventually be supported on netmf?</p> <p>Any option, eg CIL preprocessing, RTTI or new LLVM pipeline will do. Just ease the porting - this is the biggest hurdle...
  • Add Generics

    2020-12-01 19:54:26
    <div><p>Add generics to a couple of classes. Reduces raw type warnings by a couple hundred but still a long way to go. <p>Also fix indentation to consistently use spaces instead of tabs in places ...
  • Support generics

    2020-12-02 04:50:00
    <div><p>Can you support generics? Like generating from this: <pre><code>json { "title": "TGenericNumber", "type": { "$ref": "#/definitions/iarg", "...
  • Add generics

    2020-11-29 06:36:59
    <div><p>This is a complex and ...<p>This issue exists to track progress of the generics implementation in gomacro. Feel free to comment.</p><p>该提问来源于开源项目:cosmos72/gomacro</p></div>
  • Introduce generics

    2020-12-27 03:24:06
    <div><p>First pass to add generics. Most of the work was done automatically from the <a href="https://www.jetbrains.com/help/idea/generify-refactoring.html">IntelliJ Generify tool</a></p> <p>Some ...
  • 泛型Generics

    2020-04-09 20:41:10
    generics、generic type、Generic Method、Bounded Type Parameters、Wildcards、API应用举例

    Type safety means that the compiler will validate types while compiling, and throw an error if you try to assign the wrong type to a variable.
    Java is Type safety.
    在这里插入图片描述

    一、Why Use Generics?

    • Stronger type checks at compile time.
    • Elimination of casts.
    • Enabling programmers to implement generic algorithms.
           List<String> list = new ArrayList<>();
           List list1 = new ArrayList();
            /*
             1.在编译时会报异常:add (java.lang.String) in List cannot be applied to (java.lang.Integer)
             无需等到运行时,运行时报错可能比较难找错误位置
              */
            list.add(1);
    
            //2.
            //它会将list1中所有元素当成Object,向下转换要显式转换
            String str= (String)list1.get(0);
            
            String str=list.get(0);
            //3.自定义特定类型的集合
            List<Student> list=new ArrayList<>();
    

    二、generic type

    A generic type is a generic class or interface that is parameterized over types.

    //格式:
    class name<T1, T2, ..., Tn> { /* ... */ }
    
    //例子
    public class Box<T> {
        private T t;
        //构造方法
        public Box(T t)
        {
            this.t=t;
        }
        public void set(T t){
            this.t=t;
        }
    
        public T get(){
            return t;
        }
    }
    
    //调用 invokation 初始化有两种方式
    Box<String> mybox=new Box<>("str1");
    Box<String> mybox1=new Box<String>("str2");
    

    Type Parameter and Type Argument
    When coding, one provides type arguments in order to create a parameterized type.
    <T> in Box<T> 是Type Parameter;<String> in Box<String>是Type Argument

    注意:Type Argument是non-primitive也就是class、interface、array
    An invocation of a generic type is generally known as a parameterized type.

    三、Generic Method

    Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter’s scope is limited to the method where it is declared.
    也就是说:generic type的type parameter范围是整个类或接口;generic method的type parameter范围是该方法。

    public class Test {
       //Generic Method 要将type parameter写在返回类型前面
        public static <T> boolean compareTo(Box<T> t1,Box<T> t2)
        {
            return t1==t2;
        }
    
        public static  void main(String[] args) {
           Box<String> mybox=new Box<>("str1");
           Box<String> mybox1=new Box<String>("str2");
           
           System.out.println(compareTo(mybox,mybox1));
        }
    }
    

    四、Bounded Type Parameters

    There may be times when you want to restrict the types that can be used as type arguments in a parameterized type. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

    语法:
    type Parameters extends upper bound
    
    //只能接受Number及子类型 
        public <U extends Number> void inspect(U u){
            System.out.println(u.getClass().getName());
        }
        //测试:
           Test t=new Test();
            t.inspect(new Integer(1));
            t.inspect(new Double(1.0));
    

    extends is used in a general sense to mean either “extends” (as in classes) or “implements” (as in interfaces).

    1.Generics, Inheritance, and Subtypes

    在上面的inspect例子中,能够使用Integer、Double等的原因是他们均为Number子类型(subtype),也就是"is a"的关系。
    subtype:
    考虑如下场景:

     public  void inspect1(Box<Number> b){
            System.out.println(b.getClass().getName());
        }
    

    并不能接受Box<Integer>或Box<Double>,因为它们不是Box<Number>的子类。
    在这里插入图片描述
    也就是说给定具体类型A、B(比如Number、integer),MyClass<A>与MyClass<B>是没有关系的。不管A、B是否有关系。Class<A>与Class<B>的父类是Object(也就是万物即为对象)

    2.Generic Classes and Subtyping

    You can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.
    在这里插入图片描述
    ArrayList<E> implements List<E>,List<E> extends Collection<E>。So ArrayList<String>是List<String>的subtype.

    五、Type Inference

    Type inference is a Java compiler’s ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable. The inference algorithm determines the types of the arguments and, if available, the type that the result is being assigned, or returned. Finally, the inference algorithm tries to find the most specific type that works with all of the arguments.

    t.inspect(new Integer(1));//不用再写t.<Integer>inspect(new Integer(1));
    Map<String, List<String>> myMap = new HashMap<>();
    

    六、Wildcards

    In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.

    为什么需要Wildcards?

    generic type让类型更灵活,但是也存在Box<Numer>只能接受Number、不能接收父Object、子Double等问题,为了解决这些存在继承关系的问题,从而需要用Wildcards.

    //B is A's subtype
    class A { /* ... */ }
    class B extends A { /* ... */ }
    
    //可行:
    B b = new B();
    A a = b;
    
    //不可行 List<B> is not List<A>'s subtype
    List<B> lb = new ArrayList<>();// ArrayList is List's subtype
    List<A> la = lb;   // compile-time error 
    

    1.Upper Bounded Wildcards

    You can use an upper bounded wildcard to relax the restrictions on a variable. For example, say you want to write a method that works on List<Integer>, List<Double>, and List<Number>; you can achieve this by using an upper bounded wildcard.

    an upper bounded wildcard restricts the unknown type to be a specific type or a subtype of that type and is represented using the extends keyword.
    upper bounded wildcard将未知类型限制为特定类型或该类型的子类型,并使用extends关键字表示。

    extends is used in a general sense to mean either “extends” (as in classes) or “implements” (as in interfaces).

    //语法:upper bounded wildcard: <? extends upper_bound>
    public static void process(List<? extends Number> list) { /* ... */ }
    
    //调用
    process(new ArrayList<Integer>());
    //传参:List<? extends Number>  list=new ArrayList<Integer>();
    ①ArrayList 是 List的 subtype ②Numer是Integer的upper_bound.
    

    To write the method that works on lists of Number and the subtypes of Number, such as Integer, Double, and Float, you would specify List<? extends Number>. The term List<Number> is more restrictive than List<? extends Number> because the former matches a list of type Number only, whereas the latter matches a list of type Number or any of its subclasses.
    List<Number>限制比List<? extends Number>更严格。

    2.Lower Bounded Wildcards

    a lower bounded wildcard restricts the unknown type to be a specific type or a super type of that type.

    //语法:lower bounded wildcard: <? super lower_bound>
    public static void process(List<? super Integer> list) { /* ... */ }
    
    //调用
    process(new ArrayList<Integer>());
    //传参:List<? super Number>  list=new ArrayList<Integer>();
    ①ArrayList 是 List的 subtype ②Integer是Number的lower_bound.
    

    To write the method that works on lists of Integer and the supertypes of Integer, such as Integer, Number, and Object, you would specify List<? super Integer>. The term List<Integer> is more restrictive than List<? super Integer> because the former matches a list of type Integer only, whereas the latter matches a list of any type that is a supertype of Integer.

    3.Unbounded Wildcards

    • If you are writing a method that can be implemented using functionality provided in the Object class.(如果您正在编写方法,它使用Object类中提供的方法)
      If we want to have it accept all type,we can have it extends Object,which every class in Java inherits from.
      But instead of using <? extends Object>,we can simplify this to <?>
    • When the code is using methods in the generic class that don’t depend on the type parameter. For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class<T> do not depend on T.
    public static void printList(List<?> list) {
        for (Object elem: list)//elem只能用Object类的方法 若
            System.out.print(elem + " ");
        System.out.println();
    }
    //调用
    printList(new ArrayList<Integer>());
    //传参:List<? super Number>  list=new ArrayList<Integer>();
    ①ArrayList 是 List的 subtype ②?可接受任何类型
    

    It’s important to note that List<Object> and List<?> are not the same. You can insert an Object only,not List

    七、API举例

    1. ArrayList<E>中的一个构造函数:ArrayList(Collection<? extends E> c)
     //沿用B extends A
     Collection<B> ls=new ArrayList<>();// Arraylist is Collection's subtype
     (参考四中Collection-List-ArrayList关系图片)
     
     List<A> ls1=new ArrayList<>(ls);//ls中元素为B extends A √
    

    2.ArrayList<E> :add(E e)

         A al=new A();
         ls1.add(al);
         B b3=new B();
         ls1.add(b3);//B is A's subtype 
    

    3.TreeSet<E>构造函数:TreeSet(Comparator<? super E> comparator) 也就是比较器是E或父类型

    public class A {
        private  int a;
        
        public A(int a) {
            this.a = a;
        }
        //省略getter/setter
    }
    
    public class B extends A{
        public B(int a) {
            super(a);
        }
    }
    //用A做比较器
    public class MyComparator implements Comparator<A> {
        @Override
        public int compare(A o1, A o2) {
            return o1.getA()-o2.getA();
        }
    }
    

    测试:

            Comparator<A> comparator=new MyComparator();
            //E是B  比较器是B的父类A
            TreeSet<B> ts=new TreeSet<>(new MyComparator());
            ts.add(new B(1));
            ts.add(new B(2));
    

    参考:https://docs.oracle.com/javase/tutorial/java/generics/types.html

    展开全文
  • Generics in Java, Java generics 的使用 1 Introduction to generics Generics are a way to tell a compiler what type of object a collection can contain. The idea is to allow type (Integer, String, … etc...

    Generics in Java, Java generics 的使用

    1 Introduction to generics

    Generics are a way to tell a compiler what type of object a collection can contain. The idea is to allow type (Integer, String, … etc and user defined types) to be a parameter to methods, classes and interfaces. For example, classes like HashSet, ArrayList, HashMap, etc use generics very well.

    Advantages of Generics:

    Programs that uses Generics has got many benefits over non-generic code.

    • Code Reuse 代码复用: We can write a method/class/interface once and use for any type we want.

    • Type Safety 类型安全 : Generics make errors to appear compile time than at run time (It’s always better to know problems in your code at compile time rather than making your code fail at run time). Suppose you want to create an ArrayList that store name of students and if by mistake programmer adds an integer object instead of string, compiler allows it. But, when we retrieve this data from ArrayList, it causes problems at runtime.

    // A Simple Java program to demonstrate that NOT using 
    // generics can cause run time exceptions 
    import java.util.*; 
      
    class Test 
    { 
        public static void main(String[] args) 
        { 
            // Creatinga an ArrayList without any type specified 
            ArrayList al = new ArrayList(); 
      
            al.add("Sachin"); 
            al.add("Rahul"); 
            al.add(10); // Compiler allows this 
      
            String s1 = (String)al.get(0); 
            String s2 = (String)al.get(1); 
      
            // Causes Runtime Exception 
            String s3 = (String)al.get(2); 
        } 
    } 
    
    // Using generics converts run time exceptions into  
    // compile time exception. 
    import java.util.*; 
      
    class Test 
    { 
        public static void main(String[] args) 
        { 
            // Creating a an ArrayList with String specified 
            ArrayList <String> al = new ArrayList<String> (); 
      
            al.add("Sachin"); 
            al.add("Rahul"); 
      
            // Now Compiler doesn't allow this 
            al.add(10);  
      
            String s1 = (String)al.get(0); 
            String s2 = (String)al.get(1); 
            String s3 = (String)al.get(2); 
        } 
    } 
    
    • Individual Type Casting is not needed : If we do not use generics, then, in the above example every-time we retrieve data from ArrayList, we have to typecast it. (即String s1 = (String)al.get(0); ) Typecasting at every retrieval operation is a big headache. If we already know that our list only holds string data then we need not to typecast it every time.
    // We don't need to typecast individual members of ArrayList 
    import java.util.*; 
    
    class Test 
    { 
    	public static void main(String[] args) 
    	{ 
    		// Creating a an ArrayList with String specified 
    		ArrayList <String> al = new ArrayList<String> (); 
    
    		al.add("Sachin"); 
    		al.add("Rahul"); 
    
    		// Typecasting is not needed 
    		String s1 = al.get(0); 
    		String s2 = al.get(1); 
    	} 
    } 
    
    
    • Implementing generic algorithms: By using generics, we can implement algorithms that work on different types of objects and at the same they are type safe too.

    2 Generic methods in Java

    Generic methods in Java are methods that allow you to create a new type parameter just for that method. This is useful if you are writing a method but want to be flexible about the type of objects you can pass in.

    I have an array of characters called charArray. I also have an array of booleans called boolArray, and an array of integers called intArray. Then, I have created a method called arrayToList that iterates through all of the objects in an array and adds them to a list. I want to be able to pass any of these arrays into the method, even though they are of different types. So the first thing I have tried is making the arguments of the array to list method object types.

    public class GenericMethods {
    
        static Character[] charArray = {'h', 'e', 'l', 'l', 'o'};
        static Integer[] intArray = {1, 2, 3, 4, 5};
        static Boolean[] boolArray = {true, false, true};
    
        public static List arrayToList(Object[] array, List<Object> list) {
            for (Object object : array) {
                list.add(object);
            }
            return list;
        }
    
        public static void main(String[] args) {
            List<Character> charList = arrayToList(charArray, new ArrayList<>());
            List<Boolean> boolList = arrayToList(boolArray, new ArrayList<>());
            List<Integer> intList = arrayToList(intArray, new ArrayList<>());
        }
    }
    

    Using objects means that I lose type safety. For example, in the main method, if I change the type of intList to string and compile this file, I don’t get any errors.

    The solution is to make the array to list method a generic method The first thing I need to do is create a new type variable, which I will call T. This type variable only has local scope.

    public class GenericMethods {
    
        static Character[] charArray = {'h', 'e', 'l', 'l', 'o'};
        static Integer[] intArray = {1, 2, 3, 4, 5};
        static Boolean[] boolArray = {true, false, true};
    
        public static <T> List<T> arrayToList(T[] array, List<T> list) {
            for (T object : array) {
                list.add(object);
            }
            return list;
        }
    
        public static void main(String[] args) {
            List<Character> charList = arrayToList(charArray, new ArrayList<>());
            List<Boolean> boolList = arrayToList(boolArray, new ArrayList<>());
            List<Integer> intList = arrayToList(intArray, new ArrayList<>());
            System.out.println(intList.get(0));
        }
    }
    

    Using this approach, I can keep the method flexible, but I can discover errors in the code much earlier on.

    3 Using vargs in Java

    Sometimes you might want to write a method that takes a variable number of arguments. In Java there is a feature called variable-length arguments, or varargs for short, which allows you to do this.

    在写printShoppingList() method 的时候,不用让输入必须是列表,比如 printShoppingList(String[] items) , Instead,我们可以用三个点代替 [ ], 这样这个method接受多个variable输入,自动成为一个list.

    public class Varargs {
        
        public static void main(String[] args) {
            String imem1 = "Apples";        
            String item2 = "Oranges";
            String item3 = "Pears";
            printShoppingList(imem1, item2, item3);
            printShoppingList("Bread", "Milk", "Eggs", "Bananas");
        }
        
        private static void printShoppingList(String... items) {
            System.out.println("SHOPPING LIST");
            for (int i = 0; i < items.length; i++) {
                System.out.println(i + 1 + ": " + items[i]);
            }
            System.out.println();
    
        }
    }
    

    Using a vararg method has made my code shorter and simpler, but it is still easy to read and understand.

    4 The substitution principle in Java

    he substitution principle, which is also known as the Liskov Substitution Principle, is an important concept in object-oriented programming because it allows you to write maintainable and reusable code.

    It just means that if you have a variable of a given type you can assign it to a value that is a subtype of that type.

    Because office is a subtype of building, I can pass it into this method. This is the substitution principle.

    class Building {
        @Override
        public String toString() {
            return("building");
        }
    }
    
    class Office extends Building {        
       
        @Override
        public String toString() {
            return ("office");
        }
    }
    
    public class Main {
        
        
        public static void main(String[] args) {
            Building building = new Building();        
            Office office = new Office();
            build(building);
            build(office);
            
            List<Building> buildings = new ArrayList();
            buildings.add(new Building());
            buildings.add(new Office());
            printBuildings(buildings);
            
            List<Office> offices = new ArrayList();
            offices.add(new Office());
            offices.add(new Office());
            printBuildings(offices);
            
        }
        
        static void build(Building building) {
            System.out.println("Constructing a new " + building.toString());
        }
        
        static void printBuildings(List<Building> buildings) {
            for(int i = 0; i < buildings.size(); i++) {
                System.out.println(i + 1 + ": " + buildings.get(i).toString());
            }
        }
        
    }
    
    

    It is also important to know when the substitution principle does not apply. You might think that because office is a subtype of building that a list of type office is a subtype of a list of type building. However, this isn’t actually the case.

    5 Using wildcards in generic programming

    A wildcard is essentially an unknown type, and can give you more flexibility when writing methods.

    To use a wildcard, I put a question mark and then write extends. (typing) Before the word building. This means that I can now pass in lists of any type that extends the building class.

    Wildcards can also be used to specify that super types can be used when a subtype is specified. In this main class, I also have a method called addHouseToList, which takes a list of houses as an argument and adds a new house to it. Currently, I can only pass in a list of houses to this method. But if I wanted to be able to pass in a list of Buildings, I can use wildcards again. This time, I’ve put a question mark and the word super in front of house, where I specify the type of list. Now, I can pass in a list of buildings to this method.

    class Building {
        public int numberOfRooms = 7;
        @Override
        public String toString() {
            return ("building");
        }
    
        public int getNumberOfRooms() {
            return numberOfRooms;
        }
    
        public void setNumberOfRooms(int numberOfRooms) {
            this.numberOfRooms = numberOfRooms;
        }
    }
    /*****************************************/
    public class House extends Building {
     
        public int numberOfRooms = 10;
        @Override
        public String toString() {
            return ("house");
        }
                
        public int getNumberOfRooms() {
            return numberOfRooms;
        }
        
        public void setNumberOfRooms(int numberOfRooms) {
            this.numberOfRooms = numberOfRooms;
        }
    }
    
    class Office extends Building {        
        
        @Override
        public String toString() {
            return ("office");
        }
    }
    
    public class Main {
        
        
        public static void main(String[] args) {
            
            // List of buildings
            List<Building> buildings = new ArrayList();
            buildings.add(new Building());
            buildings.add(new Building());
            printBuildings(buildings);
            
            // List of offices
            List<Office> offices = new ArrayList();
            offices.add(new Office());
            offices.add(new Office());
            printBuildings(offices);
    
            // List of houses
            List<House> houses = new ArrayList();
            houses.add(new House());
            houses.add(new House());
            printBuildings(houses);
            
            addHouseToList(houses);
            addHouseToList(buildings);        
            
        }
    
        static void printBuildings(List<? extends Building> buildings) {
            for(int i = 0; i < buildings.size(); i++) {
                System.out.println(buildings.get(i).toString() + " " + (i + 1));
            }
            System.out.println();
        }
        
        static void addHouseToList(List<? super House> buildings) {
            buildings.add(new House());
            System.out.println();
        }
    }
    

    If you are unsure about when to use extends and when to use super with wildcards, you can think about invariables and outvariables. In the printBuildings method, I am passing in a list which provides data which I use inside the method, so this in an invariable. With invariables, it makes sense to use extends. In the addHouseToList method, I am using the method to give additional data by adding to the list. So this is an outvariable. And in this case it makes sense to use super.

    Also note that it is generally a bad idea to use wildcards as return types for a method.

    展开全文

空空如也

1 2 3 4 5 ... 20
收藏数 6,187
精华内容 2,474
关键字:

generics