对于泛型的基本概念就不多讲,需要了解泛型的知识点可以看下图:
泛型解决了java中对Object的任意化操作所产生的问题,这种任意化操作就是Object引用进行“向上转型”或者“向下转型”操作,但是某些操作强制类型转换的错误也许不会被编译器捕捉,而在运行的时候出现异常,可见类型转换存在安全隐患,所以在此提供安全省心的泛型类型。
泛型的初步了解
1、泛型类:
class 类名<字母,字母......>{
private 字母 属性名;
…setter与getter.
}
需要注意的是:
a) 泛型不能使用在基本类型上
b) 泛型不能使用在静态属性上
public class Student<T,T1> {
private T javase;
public Student() {
}
public Student(T javase) {
this.javase =javase;
}
public T getJavase() {
return javase;
}
public void setJavase(T javase) {
this.javase = javase;
}
}
2、泛型接口
接口中泛型字母只能使用在方法中,不能使用在全局常量中
public interface Comparator<T> {
void compare(T t);
//T Max_Value = 100; //会报错
}
3、泛型方法
泛型方法一般都是在返回值之前加<字母>,泛型方法可以在非泛型类中
public class TestMethod {
public static void main(String[] args) {
test("a"); //T -->String
}
//定义泛型方法
public static <T> void test(T a){
System.out.println(a);
}
// extends表示上限<= ...表示可变参数,例如将其换成[]就成了数组
public static <T extends Closeable> void test(T... a){
for(T temp:a){
try {
if(null!=temp){ temp.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
泛型的深入
泛型的继承
当父类为泛型的话,子类也必须要保留父类的泛型或者实现父类的泛型,而且子类泛型必须>=父类泛型,也就是会所子类的泛型可以比父类多。当子类没写父类的具体实现的话,就会默认为Object,而泛型的接口和类的继承是一样的
/**
* 泛型父类,子类为富二代
* 1、保留父类泛型 -->子类为泛型
* 2、不保留父类泛型 -->子类按需实现
*
* 属性 及方法 类型 -->随位置而定
* 1)、子类重写方法的类型 -->随父类而定
* 子类新增方法的类型 -->随子类而定
* 2)、子类中使用父类的属性 -->随父类而定
* 子类中使用自己的属性 -->随子类而定
* @author bj
*
*/
public class Class_Extends{
public abstract class Father<T1,T2> {
T1 age;
public abstract void test(T2 name);
}
//保留 -->泛型子类
//1)、全部保留
class Child1<T1,T2,A,B> extends Father<T1,T2>{
T1 age;//this.age -->T1
A Sex;
@Override
public void test(T2 name) {
}
public void test2(B b){
}
}
//2)、部分保留
class Child2<T2,A,B> extends Father<Integer,T2>{
Integer age;//this.age -->Integer
A Sex;
@Override
public void test(T2 name) {
}
public void test2(B b){
}
}
//不保留 -->按需实现
//1)、具体类型
class Child3 extends Father<Integer,String>{
Integer age;//this.age -->Integer
@Override
public void test(String name) {
}
}
//2)、没有类型 擦除 Object
@SuppressWarnings("rawtypes")
class Child4 extends Father/*<Object,Object>*/{
Object age;//this.age -->Object
@Override
public void test(Object name) {
}
}
}
泛型的擦除
public class MyStudent<T> {
private T javase;
//private static T test; //泛型不能使用在静态属性上
public MyStudent() {
}
public MyStudent(T javase) {
this.javase = javase;
}
public T getJavase() {
return javase;
}
public void setJavase(T javase) {
this.javase = javase;
}
}
public class MyStudentImpl {
/**
* 泛型的擦除: 使用时 |实现|继承 没有指定类型 ,
* 类似于 Object ,不等同于 Object
*/
public static void main(String[] args) {
//擦除 -->没有指定 泛型的具体类型
MyStudent student =new MyStudent();
student.setJavase(100); //100 -->int -->Integer -->Object
Object obj=student.getJavase();
System.out.println(obj);
test(student);//编译不会类型检查,此处不会报错,因为Object类型相当于被擦除了
MyStudent<Object> student2 =new MyStudent<Object>();
//不等于 Object
//test(student2); -->会报错,因为这个地方已经申明了Object类型,就只能是Object类型
}
public static void test(MyStudent<Integer> stu){
}
}
import java.util.ArrayList;
public class ErasedTypeEquivalence {
public static void main(String[] args) {
//我们分别定义了一个接受String类型的List和一个接受Integer类型的List,
//按照我们正常的理解,泛型ArrayList<T>虽然是相同的,但是我们给它传了不同的类型参数,
//那么c1和2的类型应该是不同的。但是结果恰恰相反,运行程序发现二者的类型时相同的。这是为什么呢?
//这里就要说到Java语言实现泛型所独有的——擦除
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2);
}
}