Java拾贝第九天——泛型

发布时间 2023-10-23 22:02:26作者: ocraft

Java拾贝不建议作为0基础学习,都是本人想到什么写什么

如果一个类中,不想限定具体类型的属性,或某个方法的返回值和传参。

可以在类声明时通过一个标识来表示。

这样只需要在实例化类的时候声明具体的类型即可,这就是泛型

泛型类

泛型作用于类上就是泛型类。

栗子:

public class Test9 {
    public static void main(String[] args) {
        MyF<String> f = new MyF<String>();
	//外部来指定类型  第二个<>中的String可以省略
        f.setName("泛型");
    }
}
class MyF<T> {
    private T name;//属性不定义具体类型

    public MyF() {
    }
    public MyF(T name) {//构造方法也可也使用泛型
        this.name = name;
    }
    public T getName() {//返回类型不定义具体类型
        return name;
    }
    public void setName(T name) {//传参不定义具体类型
        this.name = name;
    }
}

上门的MyF类就是泛型的具体体现。其调用了"<T>"形式,泛型表示具体类型是由外部实例化MyF类时指定的。

<>中可以是任意的大写字母,<A>、<B>都可以。这里采用T是type的缩写而已。

基本类型是无法指定的,只能指定引用类型

栗子:

MyF<int> f = new MyF<>();//错错错

传入的类型与泛型不一致。

栗子:

public class Test9 {
    public static void main(String[] args) {
        MyF<Integer> f = new MyF<>();
        f.setName("传入String类型");//编译错误 泛型是Integer类型
    }
}
class MyF<T> {
    private T name;

    public MyF() {
    }
    public MyF(T name) {
        this.name = name;
    }
    public T getName() {
        return name;
    }
    public void setName(T name) {
        this.name = name;
    }
}

传入的类型可以是某个类或其子类

栗子:

public class Test9 {
    public static void main(String[] args) {
        Point<Son> point = new Point<>();
	//Point<Dad> point = new Point<>();一样没问题的
    }
}
class Dad{
    
}
class Son extends Dad{
    
}
class Point<T>{
    private T name;

    public Point() {
    }

    public Point(T name) {
        this.name = name;
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }
}

静态不能使用泛型
栗子:

class Point<T>{ 
    static T t;//错错错
    public static T tell(){//编译直接报错 
    }

因为静态处于全局内存区,JVM对静态的初始化会在类实例化之前。

此时使用泛型会导致JVM初始化全局内存不成功。因为泛型是不确定的数据类型

多个泛型

public class Test9 {
    public static void main(String[] args) {
        Point<String, Integer> point = new Point<>("小明",18);
	//外部指定属性name数据类型为String,属性age数据类型为Integer
    }
}

class Point<T,K>{//任意字母都行
    private T name;
    private K age;

    public Point() {
    }

    public Point(T name, K age) {
        this.name = name;
        this.age = age;
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }

    public K getAge() {
        return age;
    }

    public void setAge(K age) {
        this.age = age;
    }
}

泛型擦除

即外部不指定具体类型

public class Test9 {
    public static void main(String[] args) {
        Point point = new Point();
        point.setName("小明");
    }
}

class Point<T>{
    private T name;

    public Point() {
    }

    public Point(T name) {
        this.name = name;
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }
}

上述栗子会出现不安全警告信息。

虽然不指定泛型类型后编译出现了警告,但是并不影响程序运行。

这是因为Java在这种情况(不指定泛型类型)下采用Object进行接收。也称泛型擦除

泛型接口

泛型作用于接口上就是泛型接口。

栗子:

interface Cat<T>{
   void getCat(T t);
}

泛型接口在被继承与被实现时确定类型

栗子:

interface Cat<T>{
   void getCat(T t);
}
interface Dog extends Cat<String>{//被继承
}
class tc implements Cat<String>{//被实现
    @Override
    public void getCat(String s) {
        System.out.println("不定义会泛型擦除,记得确定数据类型");
    }
}

泛型方法

泛型作用于方法上就是泛型方法。

栗子:

class Gen<T>{
    public <K,V> void tell(T t,K k){//可以使用泛型类中的泛型或泛型方法中的泛型
        System.out.println("泛型类中的泛型方法");
    }
}

泛型方法不光可以在泛型类中,还可以在普通类中。

class Pen{
    public <K,V> void tell(K k){//泛型不一定要全部使用
        System.out.println("普通类中的泛型方法");
    }
}

普通方法也可也使用泛型

class Gen<T>{
    public <K> void tell(T t){//泛型方法
        System.out.println("泛型类中的泛型方法");
    }
    public void say(T t){//只是传参使用泛型而已 这不是泛型方法!!!
        System.out.println("普通方法使用泛型");
    }
}