Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符

泛型

泛型的理解和好处

理解

泛型:jdk5.0出现的新特性;参数化的类型。可以将某个类型当做参数传递给类、接口或方法中

联想:

A a = new A();
class A{
	T t;
}

method("john");
public void method(String s){
	//访问s
}

区别:

方法的参数:传递的是值,必须传参,只能用在方法中
泛型:传递的是类型,可以不用传参,默认为Object,可以用在方法、类、接口中

好处

1、编译时检查待添加的元素类型,提高了类型的安全性
2、减少了类型转换的次数,提高了效率

没有使用泛型:

	String——>Object——>String

使用泛型:

	String——>String——>String

3、减少了编译警告

泛型的语法和使用 ★

语法:

类型<指定的泛型> 名 = new 类型<>();

表示形式如下:

	Set set = new HashSet();
	Set set2 = new HashSet<>();//jdk7.0 类型推断
	Set set3 = new HashSet();//为了新老版本兼容性,不推荐使用
	Set set4 = new HashSet();//为了新老版本兼容性,不推荐使用

注意:
①泛型的类型只支持引用类型
②编译类型和运行类型的泛型必须一致

自定义泛型类、泛型方法、泛型接口【了解】

一、自定义泛型类

定义语法:

class MyClass{
	T name;
	publci void setName(T t){}
}

注意:里面可以定义使用泛型的属性、方法也可以定义不使用泛型的普通属性和普通方法
但不能定义使用泛型的静态方法和使用泛型的数组初始化!

什么时候确定泛型类的具体类型?

答:创建对象时

语法:

MyClass m = new MyClass<>();

二、自定义泛型接口

定义语法:

interface MyInter{
	U method(T t);
}

什么时候确定泛型接口的具体类型?

答:被继承或实现时,可以确定,如果不确定,则默认是Object类型。如果想延续泛型,则需要将子接口或实现类设计成泛型形式!

泛型中的通配符的使用【了解】

一、泛型的好处 【面试题】

1、减少了编译警告
2、编译时检查类型,提高类型的安全性
3、大大减少了类型转换的次数,提高了效率

二、泛型的语法和使用 ★

Set set = new HashSet();
Set set = new HashSet<>();  //jdk7
Set set = new HashSet();为了兼容
Set set = new HashSet();为了兼容
Set set = new HashSet();

注意:泛型的类型 只允许引用类型!!
三、自定义泛型
1、自定义泛型类
定义语法:

class MyClass{
	T t;
	public void setT(T t){}
	public T[] getT(){return null}
}
备注:不允许有使用泛型的静态方法和使用泛型的数组初始化

什么时候确定泛型类的泛型?

创建对象时!如果没有指定泛型也不报错,只是默认Object类型

2、自定义泛型接口
定义语法:

interface MyInterface{
	T getT();
	void setT(T t);
}

什么时候确定泛型接口的泛型?
实现该接口或继承该接口!如果没有指定泛型也不报错,只是默认Object类型

3、自定义泛型方法

定义语法:

修饰符 返回类型 方法名(E e){
	
}

什么时候确定泛型?

方法被调用时!

四、泛型的继承性和通配符

一)泛型不具备继承性!

List list = new ArrayList();
 //错误!
 
  

二)通配符

?:支持任意类型。 不能添加,除了null
? extends 类A:支持类A以及A的子类。 不能添加,除了null
? super 类A:支持类A以及A的父类(不限于直接父类)。 不能添加,除了null和A的对象

示例:

List list= new ArrayList();
list.add(null);
list.add(obj);//错误!

Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第1张图片

  1. 解决元素存储的安全性问题
  2. 解决获取数据元素时,需要类型强转的问题
    Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第2张图片
    Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第3张图片
    泛型,JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。
    Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。
    Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第4张图片
    体会:使用泛型的主要优点是能够在编译时而不是在运行时检测错误。
    Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第5张图片

1.泛型的声明

	interface List 和 class GenTest 

其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。常用T表示,是Type的缩写。

2.泛型的实例化:
一定要在类名后面指定类型参数的值(类型)。如:

    List strList = new ArrayList();
    Iterator iterator = customers.iterator();

T只能是类,不能用基本数据类型填充。但可以使用包装类填充
把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第6张图片
1.对象实例化时不指定泛型的话,默认为:Object。
2. 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如
3. 泛型类的构造器如下:

public GenericClass(){}。

而如下是错误的:

public GenericClass(){}

4.从泛型类派生子类,泛型类型需具体化
5.如果泛型类是一个接口或抽象类,则不可创建泛型类的对象。
6.静态方法中不能使用类的泛型
7.异常类不能是泛型的
8.加入集合中的对象类型必须与指定的泛型类型一致。
9.泛型不同的引用不能相互赋值。

  >尽管在编译时ArrayList和ArrayList是两种类型,但是,在运行时只有一个ArrayList被加载到JVM中。

10.泛型的指定中不能使用基本数据类型,可以使用包装类替换。
11. 不能使用new E[]。但是可以:

E[] elements = (E[])new Object[capacity];

自定义泛型类

class Person{
	//使用T类型定义变量
	private T info;
	//使用T类型定义一般方法
	public T getInfo(){
		return info;
	}
	public void setInfo(T info){
		this.info = info;
	}

使用T类型定义构造器

public Person(){}
public Person(T info){
	this.info = info;
}
//static的方法中不能声明泛型
//public static void show(T t){
//}
//不能在try-catch中使用泛型定义
//try{}
//catch(MyException  ex){}		
}

对于泛型方法

方法也可以被泛型化,不管此时定义在其中的类是不是泛型类。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。

泛型方法的格式:

[访问权限]  <泛型>  返回类型  方法名([泛型标识 参数名称])  抛出的异常

例如

public class DAO {

public   E get(int id, E e){
	E result = null;
	return result;
}}

Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第7张图片
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G并不是G的子类型!

比如:String是Object的子类,但是List并不是List的子类。
Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第8张图片

public void testGenericAndSubClass() {
	Person[] persons = null;
	Man[] mans = null;
	// 而 Person[] 是 Man[] 的父类.
	persons = mans;
	Person p = mans[0];
	// 在泛型的集合上
	List personList = null;
	List manList = null;
	// personList = manList;(报错)
}

Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第9张图片
1.使用类型通配符:?
比如:List ,Map
List是List、List等各种泛型List的父类。

2.读取List的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。

3.写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。
唯一的例外是null,它是所有类型的成员。
将任意元素加入到其中不是类型安全的:

Collection c = new ArrayList();
c.add(new Object()); // 编译时错误

因为我们不知道c的元素类型,我们不能向其中添加对象。
add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。
唯一的例外的是null,它是所有类型的成员。
另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object

public static void main(String[] args) {
List list = null;
list = new ArrayList();
list = new ArrayList();
//list.add(3);
list.add(null);
	
List l1 = new ArrayList();
List l2 = new ArrayList();
l1.add(“尚硅谷");
l2.add(15);
read(l1);
read(l2);  }
static void read(List list){
	for(Object o : list){
		System.out.println(o);
}  }

有限制的通配符

允许所有泛型的引用调用
举例:

     (无穷小 , Number]

只允许泛型为Number及Number子类的引用调用

      [Number , 无穷大)

只允许泛型为Number及Number父类的引用调用


只允许泛型为实现Comparable接口的实现类的引用调用

public static void printCollection3(Collection coll){
	//Iterator只能用Iterator或Iterator.why?
	Iterator iterator  = coll.iterator();
	while(iterator.hasNext()){
		System.out.println(iterator.next());
}   }
public static void printCollection4(Collection coll){
	Iterator iterator  = coll.iterator();
	while(iterator.hasNext()){
		System.out.println(iterator.next());
}   }

范例:泛型应用

用户在设计类的时候往往会使用类的关联关系,例如,一个人中可以定义一个信息的属性,但是一个人可能有各种各样的信息(如联系方式、基本信息等),所以此信息属性的类型就可以通过泛型进行声明,然后只要设计相应的信息类即可。
Java泛型:使用泛型、泛型应用、自定义泛型、泛型继承、泛型通配符_第10张图片

你可能感兴趣的:(#,Java基础)