java泛型详解

本文详细介绍了Java泛型的概念、语法、使用细节,包括泛型的基本介绍、声明、接口、类和方法的实现。讲解了泛型如何保证类型安全性,避免运行时异常,并通过实例展示了泛型在类、接口和方法中的应用。此外,还提到了泛型的继承限制和通配符的使用。
摘要由CSDN通过智能技术生成

目录

java泛型详解

泛型基本介绍

泛型的语法

泛型的声明

泛型的使用细节

自定义泛型类

基本语法

注意细节

自定义泛型接口

基本语法

注意细节

自定义泛型方法

基本语法

注意细节


java泛型详解

泛型基本介绍

  • 泛型可以理解为:可以接收数据类型的数据类型

  • 泛型又称参数化类型,是 jdk5.0 出现的新特性,解决数据类型的安全性问题

  • 在类声明或实例化时只要指定好需要的具体的类型即可

  • java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生 ClassCastException(类型转换异常) 异常。同时,代码更加简洁、健壮

  • 泛型的作用是:可以在类声明时通过一个标识符表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。

泛型的语法

泛型的声明

  • interface 接口 <T>{} 和 class 类<K,V>{}。比如:List、ArrayList

说明:(1)其中,K,T,V不代表值,而是表示类型

(2)任意字母都可以。常用T表示,是Type的缩写

泛型的使用细节

  • interface List <T> {},public class HashSet<E> {}...等等

    • 说明:T、E 只能是引用类型

  • 在给泛型指定具体类型后,可以传入该类型或者其子类类型

public class Demo07 {
    public static void main(String[] args) {
        Pig<A> aPig = new Pig<A>(new A());
        aPig.f();
        Pig<A> bPig = new Pig<A>(new B());
        bPig.f();
    }
}
class A {}
class B extends A{}
class Pig<E> {
    E e;
    public Pig(E e) {
        this.e = e;
    }
    public void f() {
        System.out.println(e.getClass());
    }
}

  • 泛型的使用形式

    • 在实际开发中,我们往往简写,编译器会进行类型推断

ArrayList<Integer> integers = new ArrayList<Integer>();
ArrayList<Integer> integers2 = new ArrayList<>();//推荐写法
List<Integer> list = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<>();//推荐写法
  • 如果没有给泛型指定具体的数据类型,默认是 Object 类型

ArrayList integers = new ArrayList();
//等价于
ArrayList<Object> integers2 = new ArrayList<>();

自定义泛型类

基本语法

class 类名<T,R......>{

成员

}

注意细节

  • 普通成员可以使用泛型(属性、方法)

  • 使用泛型的数组不能初始化,因为在new的时候不能确定类型,就无法在内存上开辟空间

  • 静态属性和静态方法不能使用类的泛型,因为在类加载时,对象还没有创建,就无法确定具体的类型,JVM也就无法完成初始化

  • 泛型类的类型,是在创建对象时确定的 (因为创建对象时,需要指定确定类型)

  • 如果在创建对象时,没有指定类型,默认是Object

  • 泛型的标识符一般是单个大写字母

public class Demo06 {
    public static void main(String[] args) {
        Person<String> person = new Person<String>("我为杰伦代言");
        Person<Integer> person2 = new Person<Integer>(100);
        person.show();
        person2.show();
    }
}
class Person<E> {
    //E表示s的数据类型,E具体的数据类型在定义Person对象的时候指定
    //即在编译期间,就确定E是什么类型
    E s;
    //E可以是参数类型
    public Person(E s) {
        this.s = s;
    }
    //E可以是返回值类型
    public E f() {
        return s;
    }
    public void show() {
        System.out.println(s.getClass());
    }
}

自定义泛型接口

基本语法

interface 接口名<T,R......>{

}

注意细节

  • 接口中,静态成员也不能使用泛型

  • 泛型接口的类型,在继承接口或者实现接口时确定

  • 没有指定类型,默认为Object

public class Demo09 {
    public static void main(String[] args) {
​
    }
}
interface  IUsb<U,R> {
    //在普通方法中使用接口泛型
    R get(U u);
    void hi(R r);
    void run(R r1,R r2,U u1,U u2);
    //在jdk8中,可以在接口中使用默认方法,也是可以使用泛型
    default R method(U u) {
        return null;
    }
}
interface IA extends IUsb<String,Double> {
​
}
class AA implements IA {
    @Override
    public Double get(String s) {
        return null;
    }
    @Override
    public void hi(Double aDouble) {
​
    }
    @Override
    public void run(Double r1, Double r2, String u1, String u2) {
​
    }
}
class BB implements IUsb<Integer,Float> {
    @Override
    public Float get(Integer integer) {
        return null;
    }
    @Override
    public void hi(Float aFloat) {
​
    }
    @Override
    public void run(Float r1, Float r2, Integer u1, Integer u2) {
​
    }
}

自定义泛型方法

基本语法

修饰符<T,R...> 返回类型 方法名(参数列表) {

}

注意细节

  • 泛型方法,可以定义在普通类中,也可以定义在泛型类中

  • 当泛型方法被调用时,类型就会被确定

  • public void eat(E e) {},修饰后没有<T,R...>,eat()方法不是泛型方法,而是使用了泛型

public class Demo10 {
    public static void main(String[] args) {
        Car car = new Car();
        car.fly("宝马",100);
        System.out.println("===============");
        car.fly(300,100.1);
        System.out.println("===============");
        Fish<String, ArrayList> fish = new Fish<>();
        fish.hello(new ArrayList(),11.3f);
    }
}
class Car {
    //普通方法
    public void run(){
​
    }
    //泛型方法
    //是提供给fly方法使用的
    public<T,R> void fly(T t,R r) {
        System.out.println(t.getClass());
        System.out.println(r.getClass());
    }
}
class Fish<T,R> {
    //泛型方法
    public<U,M> void eat(U u,M m) {
​
    }
    //hi方法不是泛型方法
    //而是hi方法使用了类声明的泛型
    public void hi(T t) {
​
    }
    public<K> void hello(R r,K k) {
        System.out.println(r.getClass());
        System.out.println(k.getClass());
    }
}

泛型的继承和通配符

  • 泛型不具备继承性

错误的写法:ArrayList<Object> strings = new ArrayList<String>();

  • <?> :支持任意泛型类型

  • <? extends A>:支持A类以及A类的子类,规定了泛型的上限

  • <? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

public class Demo11 {
    public static void main(String[] args) {
        List<Object> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        List<AA> list3 = new ArrayList<>();
        List<BB> list4 = new ArrayList<>();
        List<CC> list5 = new ArrayList<>();
​
        printCollection1(list1);
​
        printCollection2(list3);
        printCollection2(list4);
        printCollection2(list5);
​
        printCollection3(list1);
        printCollection3(list3);
    }
    public static void printCollection1(List<?> c) {
        for (Object object : c) {
            System.out.println(object);
        }
    }
    public static void printCollection2(List<? extends AA> c) {
        for (Object object : c) {
            System.out.println(object);
        }
    }
    public static void printCollection3(List<? super AA> c) {
        for (Object object : c) {
            System.out.println(object);
        }
    }
}
class AA {
​
}
class BB extends AA {
​
}
class CC extends BB {
​
}

JUnit的使用

为什么需要JUnit

  • 一个类有很多功能代码需要测试,为了测试,就需要写入到main方法中

  • 如果有多个功能代码测试,就需要来回注销和切换,很麻烦

  • 如果可以直接运行一个方法,就方便很多,并且可以给出相关信息,就好了,所以需要JUnit来解决

JUnit基本介绍

  • JUnit是一个Java语言的单元测试框架

  • 多数Java的开发环境都已经集成了JUnit作为单元测试的工具

public class Demo12 {
    public static void main(String[] args) {
​
    }
    @Test
    public void m1() {
        System.out.println("m1方法被调用");
    }
    public void m2() {
        System.out.println("m2方法被调用");
    }
}

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值