Introduction to Java generics, defining and using generic classes, defining and using generic methods, defining and using generic interfaces, generic wildcards?, restricted generics

Introduction to generics:

The type of data stored in the collection is called generic. Generic is an unknown data type. You can use generic when you don’t know what data type to use;

When creating an object, specify the data type and assign it to the generic type; the generic type can also be regarded as a variable for storing data.

In common generic types: the letter E represents the element, and the letter T represents the Type. Of course, if the data type of the generic type is known, a certain data type can be passed in, such as String. The bottom layer actually passes the String to E

import java.util.ArrayList;//导包
import java.util.Iterator;
public class Generic{
    
    
    public static void main(String[] args){
    
    
        // 1.集合中为了安全,一般是需要指定数据类型的,<类型>,类型值除int(Integer)、char(Character),其它类型将数据类型的首字母大写即可
        ArrayList<String> arraylist = new ArrayList<String>();
        arraylist.add("星期一");
        System.out.println(arraylist); // [星期一]
        arraylist.add("星期二");
        System.out.println(arraylist); // [星期一, 星期二]

        // 2.使用泛型的好处:避免数据类型转换,存什么类型取什么类型;将运行期异常提升到了编译器;泛型的弊端:指明数据类型后只能存储指定类型的数据。
        ArrayList<Integer> arrayInt = new ArrayList<Integer>();
        arrayInt.add(10);
        System.out.println(arrayInt);
        // arrayInt.add("20"); // 泛型是什么类型,在新增数据的时候就是什么数据类型的数据,否则编译不通过
        arrayInt.add(20);
        System.out.println(arrayInt);

        // 3.集合不使用泛型时,默认数据类型是Object,可以存储任意类型的数据,此时不安全会发生异常。
        ArrayList list = new ArrayList();
        list.add('1');
        list.add("abc");
        list.add(12);
        System.out.println(list); // 编译时提示: Generic.java使用了未经检查或不安全的操作; 打印结果:[1, 1, abc]

        // 4.使用迭代器遍历list:
        // 获取集合的迭代器:
        Iterator iter = list.iterator();
        //遍历并打印数据:
        //hasNext判断是否有元素
        while (iter.hasNext()) {
    
    
            // next获取元素
            Object item = iter.next();
            System.out.println(item);

            // 向下转型时会抛出异常:Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String at Generic.main(Generic.java:37),使用泛型约束后在编译时就会提示
            String str = (String) item;
            System.out.println(str.length());
            System.out.println(str);
        }
    };
};

Define and use classes with generics:

When defining a generic class, you only need to add <type> after the class name, and the data type in the class is replaced by the type in angle brackets. When using a generic class, it is created in the same way as a normal class. The difference is that you can use generics to create objects, or Objects can be created without generics, but when objects are created without generics, it defaults to the Object type, and it is not recommended, as in the use of E below:

Generic class:

// 定义含有泛型的类时,在类名称后面写<类型>即可,E表示任意元素的泛型
public class GenericClass<E> {
    
    
//public class GenericClass{
    
    
    // 1.定义一个含有泛型的类(模拟ArrayList集合),泛型是一个未知的数据类型,当不确定数据类型的时候可以使用泛型,泛型可以接收任意数据类型,在创建对象时在指明数据类型:
    private E name;
//    private String name;

    public E getName() {
    
    
//    public String getName() {
    
    
        return name;
    }

    public void setName(E name) {
    
    
//    public void setName(String name) {
    
    
        this.name = name;
    }
};

Use a generic class:

public class UserGenerIcClass {
    
    
    public static void main(String[] args) {
    
    
        // 1.使用GenericClass类,不传泛型时默认是Object类型
        GenericClass gc = new GenericClass();
        // 当创建类的时候,如果数据类型是写死的,那么在这里设置和读取的时候也只能是指定写死的类型,如:
        gc.setName("苦海");
        System.out.println(gc.getName());// 苦海

        // 2.使用泛型创建对象:
        GenericClass<Integer> gcInt = new GenericClass<Integer>();
        // gcInt.setName('1'); 使用了泛型,如果数据类型不符合就会编译不通过
        gcInt.setName(18);
        System.out.println(gcInt.getName());// 18

        GenericClass<Character> gcChar = new GenericClass<Character>();
        gcChar.setName('f');
        System.out.println(gcChar.getName());// f
    }
}

Define and use methods with generics:

Define a method with generics:

// 含有泛型的方法:泛型定义在方法修饰符和返回值之间,如: public <泛型> 返回值类型(参数(使用泛型)){}
public class DefGenericMethodsClass {
    
    
    // 前面定义了泛型,后面括号中才可以使用:这里S是随便写的,这里可以写任意字符串
    public <S> void defGenericMethods(S s) {
    
    
        System.out.println(s);
    }

    // 定义一个含有泛型的静态方法:
    public static <S> void staGenericMethods(S s) {
    
    
        System.out.println(s);
    }

    // 定义一个普通的方法:
    public static void commonMethods (String s) {
    
    
        System.out.println(s);
    }
}


Use a generic method:

public class UseGenericMethodsClass {
    
    
    public static void main(String[] args) {
    
    
        // 创建含有泛型方法的对象:
        DefGenericMethodsClass gm = new DefGenericMethodsClass();
        // 调用含有泛型的方法,传递什么类型,泛型就是什么类型
        gm.defGenericMethods(10); // 10
        gm.defGenericMethods('a'); // a
        gm.defGenericMethods("121"); // 121

        // 调用静态方法:
        DefGenericMethodsClass.staGenericMethods("静态方法");
        // 调用普通方法:接收参数时必须指定类型,且传参数时也要求一直
        gm.commonMethods("hello");
        // gm.commonMethods(true); // 定义什么类型,传递什么类型,否则报错
        // gm.commonMethods(123);
    }
}

Define and use an interface with generics:

Define an interface with generics:

// 定义含有泛型的接口:在接口名称后面加<类型>
public interface DefGenericInterface<S> {
    
    
    // 定义一个抽象方法:
    public abstract void methods(S s);
}

There are two ways to use an interface with generics:

Method 1 interface implementation class:

// 使用含有泛型的接口第一种方式:定义接口实现类,实现接口,指定接口泛型:
public class UseGenericInterface implements DefGenericInterface<String> {
    
    
    @Override
    public void methods(String s) {
    
    
        System.out.println(s);
    };
}

Method 1 uses the interface implementation class:,

// 定义一个普通的类使用接口实现类:
public class UseGenericInterfaceClass {
    
    
    public static void main(String[] args) {
    
    
        UseGenericInterface gi = new UseGenericInterface();
        gi.methods("hello"); // hello
    }
}

Mode 2 interface implementation class:

// 使用含有泛型的接口第二种方式:接口使用什么泛型,实现类就用什么泛型,类跟着接口走,相当于定义了一个含有泛型的类,创建对象时指定泛型的类型
public class UseGenericInterfaceTwo<S> implements DefGenericInterface<S> {
    
    
    @Override
    public void methods(S s) {
    
    
        System.out.println(s);
    };
}

Method 2 uses the interface implementation class:

public class UseGenericInterfaceClassTwo {
    
    
    public static void main(String[] args) {
    
    
        UseGenericInterfaceTwo<Integer> gi = new UseGenericInterfaceTwo<Integer>();
        gi.methods(255); // 255
    }
}

Generic wildcard?:

When using a generic class or interface, the generic type is uncertain in the passed data, which can be represented by the wildcard <?>. But once the generic wildcard is used, only the common methods in the Objet class can be used, and the methods of the elements in the collection cannot be used. They can only receive data and cannot store data in the collection:

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

// 泛型通配符:只能作为方法的参数使用,不能创建对象使用,如下面定一个万能遍历结合的方法
public class GenericWildcard {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        list1.add(1);
        list1.add(2);
        forEachArrayList(list1);

        ArrayList<Character> list2 = new ArrayList<Character>();
        list2.add('z');
        list2.add('a');
        forEachArrayList(list2);
    }
    public static void forEachArrayList(ArrayList<?> list) {
    
    
        // 获取遍历器:
        Iterator<?> item = list.iterator();
        while(item.hasNext()){
    
    
            Object it = item.next();
            System.out.println(it);
        }
    }
}

Restricted generics:

There is no limit when setting generics before, as long as it is a class, it can be set, but in Java generics, you can specify a generic upper and lower limit:

Generic upper limit: only this type and its subclasses can be accepted

Format: type name <? extends class> object name

Generic lower limit: only this class and its parent class can be received

Format: type name <? super class> object name

import java.util.ArrayList;
import java.util.Collection;

public class GenericLimit {
    
    
    public static void main(String[] args) {
    
    
        // 定义多个类型的集合并测试受限泛型:
        Collection<Integer> list1 = new ArrayList<Integer>();
        getElementExtends(list1);
        // getElementSuper(list1); // 报错:只能传入当前类型或父类

        Collection<String> list2 = new ArrayList<String>();
        // getElementExtends(list2); // 报错:String和Number没有上下级关系
        // getElementSuper(list2); // 报错:String和Number没有上下级关系

        Collection<Number> list3 = new ArrayList<Number>();
        getElementExtends(list3);
        getElementSuper(list3);

        Collection<Object> list4 = new ArrayList<Object>();
        getElementExtends(list3);
        getElementSuper(list3);
    }
    // 类之间的继承关系:
    // Integer 继承-> Number 继承-> Object
    // String 继承-> Object

    // 定义一个泛型下限:传入的类型只能是Number或子类
    public static void getElementExtends(Collection<? extends Number> param){
    
    };
    // 定义一个泛型上限:传入的类只能是Number或父类
    public static void getElementSuper(Collection<? super Number> param){
    
    };
}

Tips: The pictures and other materials in this article come from the Internet. If there is any infringement, please send an email to the mailbox: [email protected] to contact the author to delete it.
Author: sea of ​​bitterness

Guess you like

Origin blog.csdn.net/weixin_46758988/article/details/128088586