Example Java generics - generic methods, class, interface,

Java Genrics is one of the most important features introduced in Java 5.

If you've been using the Java Collections and use version 5 or later, then I'm sure you've used it.

Java, has collections of generics is very easy, but it provides more functionality than just create collection types.

We will try to learn the generic function in this article. If we use the terminology, understanding of the generic sometimes become confusing, so I'll try to keep it simple and easy to understand.

1. Java in generics

Java 5 generics added to provide type checking at compile time, and eliminates the ClassCastExceptioncommon use of collections risk. The entire collection framework have been rewritten to use the generic type-safe. Let's see how generics help us to safely use collection classes.

List list = new ArrayList();
list.add("abc");
list.add(new Integer(5)); 

for(Object obj : list){
    
    String str=(String) obj; 
}

The above code can be compiled very well, but at run time throws ClassCastException, because we try to list the objects cast to String, and one of the elements is of type Integer. After Java 5, we use the following collection classes.

List<String> list1 = new ArrayList<String>(); // java 7 ? List<String> list1 = new ArrayList<>(); 
list1.add("abc");
//list1.add(new Integer(5)); //编译错误

for(String str : list1){
     //no type casting needed, avoids ClassCastException
}

Note that when you create a list, we have specified the type of elements in the list to a String. So, if we try to add any other type of object in the list, the program will lead to a compile-time error. Also note that, in the loop, we do not need to type conversion elements in the list, and therefore deleted ClassCastException at runtime.

2. Java generic class

We can use the generic type definition own class. Generic type is parameterized by a class or interface type. We use angle brackets (<>) to specify the type parameter.

In order to understand the benefits, we assume that there is a simple class:


package com.journaldev.generics;

public class GenericsTypeOld {

    private Object t;

    public Object get() {
        return t;
    }

    public void set(Object t) {
        this.t = t;
    }

        public static void main(String args[]){
        GenericsTypeOld type = new GenericsTypeOld();
        type.set("Pankaj"); 
        String str = (String) type.get(); //type casting, error prone and can cause ClassCastException
    }
}


Note that when using these, we must use the type conversion, and it can produce ClassCastException at runtime. Now, we will use the following alternative Java generic class is the same class.


package com.journaldev.generics;

public class GenericsType<T> {

    private T t;
    
    public T get(){
        return this.t;
    }
    
    public void set(T t1){
        this.t=t1;
    }
    
    public static void main(String args[]){
        GenericsType<String> type = new GenericsType<>();
        type.set("Pankaj"); //valid
        
        GenericsType type1 = new GenericsType(); //raw type
        type1.set("Pankaj"); //valid
        type1.set(10); //valid and autoboxing support
    }
}


Note that the main method used GenericsType class. We do not need to type conversion, and you can delete ClassCastException at runtime. If we do not provide the type when creating the compiler will issue a warning, "GenericsType is the original type.

Generic type GenericsType Reference should be parameterized. "When we do not provide the type that becomes a type Object , so it allows String and Integer object. However, we should always try to avoid this situation, because an error while processing possible run when the original type, we must use the type conversion.

Note also that it supports Java autoboxing.

3. Java common interface

Comparable interface is a good example of a generic interface, it is written as:


package java.lang;
import java.util.*;

public interface Comparable<T> {
    public int compareTo(T o);
}


In a similar way, we can create a common interface in Java. We can also have multiple types of parameters like Map interface. Similarly, we can also provide parametric values for the parameter types, e.g. new HashMap<String, List<String>>();effective.

4. Java generic type

Java generic type naming conventions can help us to easily understand the code, and has the naming convention is one of the best practices in the Java programming language. Therefore, generics also comes with its own naming conventions. Typically, a single type parameter name in capital letters, to be implemented separately from the Java variable region. The most commonly used type parameter names are:

  • E - element widely used by the Java Collections Framework, such as ArrayList, Set, etc.
  • K - Key (use in a Map)
  • N - Digital
  • T - type
  • V - value (used in a Map)
  • S, U, V, etc. - the second, third, fourth type

5. Java generic methods

Sometimes we do not want the whole class is parameterized, in this case, we can create a java generic method. Since the constructor is a special method, so we can use the generic type in the constructor.

This is a display example of a method of the generic Java class.


package com.journaldev.generics;

public class GenericsMethods {

    //Java Generic Method
    public static <T> boolean isEqual(GenericsType<T> g1, GenericsType<T> g2){
        return g1.get().equals(g2.get());
    }
    
    public static void main(String args[]){
        GenericsType<String> g1 = new GenericsType<>();
        g1.set("Pankaj");
        
        GenericsType<String> g2 = new GenericsType<>();
        g2.set("Pankaj");
        
        boolean isEqual = GenericsMethods.<String>isEqual(g1, g2);
        //above statement can be written simply as
        isEqual = GenericsMethods.isEqual(g1, g2);
        //This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.
        //Compiler will infer the type that is needed
    }
}


Note _ The isEqual_ method signature shows the syntax for using generic types in the method. Also, please note that the use of these methods in our Java programs. We can specify the type when calling these methods, you can also call them as a regular method. Java compiler is smart enough to determine the type of a variable can be used, this function is called type variables .

6. Java generic type parameter binding

Suppose we want to limit the object may be used in the type of parameterized type, for example, in a method to compare two objects, and to make sure that we accept objects are comparable. To declare a bounded type parameters, please list the name of the type of the parameter, and then expand keyword lists, coupled with its upper limit, the following method.

public static <T extends Comparable<T>> int compare(T t1, T t2){
        return t1.compareTo(t2);
}

Similar calls and unbounded these methods, except that, if we try to use any non Comparable classes, compile-time error is thrown.

Binding type parameter may be used with the methods and classes and interfaces.

Java also supports a plurality of generic range, i.e., <T extended A & B & C>. In this case, A may be a class or an interface. If a Class A, B and C should be the interface. In multiple ranges, we can not have more than one class.

7. Java generics and inheritance

We know that if A is a subclass of B, then the Java inheritance allows us to assign a variable to another variable B. A So, we may think may be assigned to any of the generic type A generic type B, but it is not. Let's look at a simple program.

package com.journaldev.generics;

public class GenericsInheritance {

    public static void main(String[] args) {
        String str = "abc";
        Object obj = new Object();
        obj=str; // works because String is-a Object, inheritance in java
        
        MyClass<String> myClass1 = new MyClass<String>();
        MyClass<Object> myClass2 = new MyClass<Object>();
        //myClass2=myClass1; // compilation error since MyClass<String> is not a MyClass<Object>
        obj = myClass1; // MyClass<T> parent is Object
    }
    
    public static class MyClass<T>{}

}

8. Java generic classes and subtype

We can expand or to achieve a common generic class or interface. The relationship between the parameters and the type of another type parameter or a class or interface determined by the interface and extend implemented clauses.

For example, ArrayList Implemented extensions Collection The List Therefore ArrayList List is Subtypes, and List Is Collection Subtype.

They do not change the parameter type, sub-type relationship will be retained, the following shows an example of multiple type parameters.

interface MyList<E,T> extends List<E>{
}

List Subtype may be MyList <String, Object>, MyList <String, Integer> and the like.

9. Java-class communication Hythe

Question mark (?) Is a wildcard generics, represent an unknown type. Wildcards can be used as an argument, field, or type of local variables, return type and sometimes can also be used. General procedure when calling or instantiating a generic class, can not use wildcards. In the following sections, we will study the upper bound wildcard wildcards and lower bound wildcard capture.

9.1) bound on Java generics wildcard

To relax the restrictions on the upper limit of the wildcard in the process variable types. Suppose we want to write a will return a list of numbers in the sum method, then we will achieve this.

public static double sum(List<Number> list){
    double sum = 0;
    for(Number n : list){
        sum += n.doubleValue();
    }
    return sum;
}

Now, to achieve the above-mentioned problem is that it does not apply to Integers or Doubles, because we know List And List Irrelevant, which is useful when using high-level wildcards. We will generic wildcard and extends keywords and the higher use the class or interface, which will allow us to deliver superior sub-class type of argument.

It can be modified to achieve the above as below the same program.

package com.journaldev.generics;

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

public class GenericsWildcards {

    public static void main(String[] args) {
        List<Integer> ints = new ArrayList<>();
        ints.add(3); ints.add(5); ints.add(10);
        double sum = sum(ints);
        System.out.println("Sum of ints="+sum);
    }

    public static double sum(List<? extends Number> list){
        double sum = 0;
        for(Number n : list){
            sum += n.doubleValue();
        }
        return sum;
    }
}

According to an interface like writing code, as in the above method, we can use all methods limit the number of classes. Note that for the upper bound of the list, in addition to the air, we do not allow any object to add to the list. If we try in the sum method to add elements to the list, the program will not compile.

9.2) Java Generics unrestricted wildcard

Sometimes, we hope common method is applicable to all types, in this case, you can use unbounded wildcard. And use <? extends Object>.

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

We can offer List method to _PrintData_ Or List Or any other type of Object parameter list. And the upper limit is similar to the list, we can add anything to the list.

9.3) Java Generics lower bound wildcard

Suppose we want to add a whole list of integers in the way, we can keep the parameter type List But can be bundled together with Integers, while List And List 也可以容纳整数,因此我们可以使用下限通配符来实现。我们使用超级关键字和下限类的泛型通配符(?)来实现此目的。

我们可以传递下界或下界的任何超类型作为参数,在这种情况下,java编译器允许将下界对象类型添加到列表中。

public static void addIntegers(List<? super Integer> list){
    list.add(new Integer(50));
}

 10.使用泛型通配符进行子类型化

List<? extends Integer> intList = new ArrayList<>();
List<? extends Number>  numList = intList;  // OK. List<? extends Integer> is a subtype of List<? extends Number>

11. Java泛型类型重构

添加了Java泛型以在编译时提供类型检查,并且在运行时没有使用,因此Java编译器使用类型更改功能删除字节码中的所有泛型类型检查代码,并在必要时插入类型转换。类型定义可确保不会为参数化类型创建新的类;因此,泛型不会产生运行时浪费。

例如,如果我们有如下通用类;


public class Test<T extends Comparable<T>> {

    private T data;
    private Test<T> next;

    public Test(T d, Test<T> n) {
        this.data = d;
        this.next = n;
    }

    public T getData() { return this.data; }
}

Java编译器用第一个绑定接口Comparable替换有界类型参数T,如下代码:


public class Test {

    private Comparable data;
    private Test next;

    public Node(Comparable d, Test n) {
        this.data = d;
        this.next = n;
    }

    public Comparable getData() { return data; }
}

12.泛型常见问题解答

12.1)为什么我们在Java中使用泛型?

泛型提供了强大的编译时类型检查,并降低了ClassCastException和显式对象转换的风险。

12.2)泛型中的T是什么?

我们使用 创建通用类,接口和方法。我们在使用T时将其替换为实际类型。

12.3)泛型如何在Java中工作?

通用代码可确保类型安全。编译器使用类型预先在编译时删除所有类型参数,以减少运行时的重载。

13. Java泛型–进一步阅读

  • 泛型不支持子类型,因此List<Number> numbers = new ArrayList<Integer>();将不进行编译
  • 我们无法创建通用副本,因此List<Integer>[] array = new ArrayList<Integer>[10]无法编译

这是所有的Java泛型,Java泛型是非常庞大的,需要大量的时间来了解和有效地使用它。本文提供了泛型的基本细节,以及如何使用泛型来扩展程序的类型安全性。


“不积跬步,无以至千里”,希望未来的你能:有梦为马 随处可栖!加油,少年!

关注公众号:「Java 知己」,每天更新Java知识哦,期待你的到来!

  • 发送「Group」,与 10 万程序员一起进步。
  • 发送「面试」,领取BATJ面试资料、面试视频攻略。
  • 发送「玩转算法」,领取《玩转算法》系列视频教程。
  • 千万不要发送「1024」...


每日福利

posted @ 2019-10-25 13:37  Java知己 阅读( ...) 评论( ...) 编辑 收藏

Guess you like

Origin www.cnblogs.com/java-friend/p/11737569.html