目录
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方法被调用");
}
}