1、为什么要学泛型?
通过两段代码我们就可以知道为何我们需要泛型

实际开发中,经常有数值类型求和的需求,例如实现int类型的加法, 有时候还需要实现long类型的求和, 如果还需要double类型的求和,需要重新在重载一个输入是double类型的add方法。
2、泛型类:
注意:泛型一定要加<T>
public class NormalGeneric<T> {
private T data;
public NormalGeneric() {
}
public NormalGeneric(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static void main(String[] args) {
NormalGeneric<String> normalGeneric = new NormalGeneric<>();
normalGeneric.setData("OK");
//normalGeneric.setData(1);
System.out.println(normalGeneric.getData());
NormalGeneric normalGeneric1 = new NormalGeneric();
normalGeneric1.setData(1);
normalGeneric1.setData("dsf");
}
}
3、泛型接口:
//泛型接口
public interface Genertor<T> {
public T next();
}
//泛型接口实现泛型接口
public class ImplGenertor<T> implements Genertor<T> {
@Override
public T next() {
return null;
}
}
//泛型接口最终实现
public class ImplGenertor2 implements Genertor<String> {
@Override
public String next() {
return null;
}
}
4、泛型方法:
//普通类中的泛型方法
public class GenericMethod {
public <T> T genericMethod(T...a){
return a[a.length/2];
}
public void test(int x,int y){
System.out.println(x+y);
}
public static void main(String[] args) {
GenericMethod genericMethod = new GenericMethod();
genericMethod.test(23,343);
System.out.println(genericMethod.<String>genericMethod("mark","av","lance"));
System.out.println(genericMethod.genericMethod(12,34));
}
}
//泛型类里的泛型方法
public class GenericMethod2 {
//这个类是个泛型类,在上面已经介绍过
public class Generic<T>{
private T key;
public Generic(T key) {
this.key = key;
}
//虽然在方法中使用了泛型,但是这并不是一个泛型方法。
//这只是类中一个普通的成员方法,只不过他的返回值是在声明泛型类已经声明过的泛型。
//所以在这个方法中才可以继续使用 T 这个泛型。
public T getKey(){
return key;
}
/**
* 这个方法显然是有问题的,在编译器会给我们提示这样的错误信息"cannot reslove symbol E"
* 因为在类的声明中并未声明泛型E,所以在使用E做形参和返回值类型时,编译器会无法识别。
*/
// public E setKey(E key){
// this.key = key;
// }
}
/**
* 这才是一个真正的泛型方法。
* 首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
* 这个T可以出现在这个泛型方法的任意位置.
* 泛型的数量也可以为任意多个
* 如:public <T,K> K showKeyName(Generic<T> container){
* ...
* }
*/
//这也不是一个泛型方法,这就是一个普通的方法,
// 只是使用了Generic<Number>这个泛型类做形参而已。
public void show(Generic<Number> obj){
}
/**
* 这个方法是有问题的,编译器会为我们提示错误信息:"UnKnown class 'E' "
* 虽然我们声明了<T>,也表明了这是一个可以处理泛型的类型的泛型方法。
* 但是只声明了泛型类型T,并未声明泛型类型E,因此编译器并不知道该如何处理E这个类型。
*/
// public <T,E> T show(E ab){
// //
// }
/**
* 这个方法也是有问题的,编译器会为我们提示错误信息:"UnKnown class 'T' "
* 对于编译器来说T这个类型并未项目中声明过,因此编译也不知道该如何编译这个类。
* 所以这也不是一个正确的泛型方法声明。
}
*/
// public void show(T obj){
//
// }
public static void main(String[] args) {
}
}
//泛型使用
public class GenericMethod3 {
static class Fruit{
@Override
public String toString() {
return "fruit";
}
}
static class Apple extends Fruit{
@Override
public String toString() {
return "apple";
}
}
static class Person{
@Override
public String toString() {
return "Person";
}
}
static class GenerateTest<T>{
//普通方法
public void show_1(T t){
System.out.println(t.toString());
}
//在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型。
// 可以类型与T相同,也可以不同。
//由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,
// 编译器也能够正确识别泛型方法中识别的泛型。
public <E> void show_3(E t){
System.out.println(t.toString());
}
//在泛型类中声明了一个泛型方法,使用泛型T,
// 注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。
public <T> void show_2(T t){
System.out.println(t.toString());
}
}
public static void main(String[] args) {
Apple apple = new Apple();
Person person = new Person();
GenerateTest<Fruit> generateTest = new GenerateTest<>();
generateTest.show_1(apple);
//generateTest.show_1(person);
generateTest.show_2(apple);
generateTest.show_2(person);
generateTest.show_3(apple);
generateTest.show_3(person);
}
}
5、限定类型变量
1、extends:类型变量的限定-方法上
//T extends ArrayList&Comparable,继承的类只能有一个,可以多个接口,使用&连接符。
public class ArrayAlg {
// public static <T> T min(T a,T b){
// if(a.comapareTo(b)>0) return a; else return b;
// }
public static <T extends ArrayList&Comparable> T min(T a, T b){
if(a.compareTo(b)>0) return a; else return b;
}
static class Test{}
public static void main(String[] args) {
//ArrayAlg.min(new Test(),new Test());
}
}
2、类型变量的限定-类上
//泛型类中使用 extends 也是一样的
public class ClassBorder<T extends Comparable> {
private T data;
public T min(T outter){
if(this.data.compareTo(outter)>0)
return outter;
else
return this.data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static void main(String[] args) {
ClassBorder<String> classBorder = new ClassBorder<>();
classBorder.setData("mark");
System.out.println(classBorder.min("av"));
}
}
6、泛型的约束和局限性
1、不能实例化类型变量;
2、静态域或者方法里不能引用类型变量;
3、静态方法 本身是泛型方法就行;
4、所有的基础类型,必须是包装类才行;
5、泛型不支持instanceof使用;
6、可以定义数组,不能使用数组;
7、泛型类不能 extends Exception/Throwable;
8、不能捕获泛型类对象;
public class Restrict<T> {
private T data;
//不能实例化类型变量
// public Restrict() {
// this.data = new T();
// }
//静态域或者方法里不能引用类型变量
//private static T instance;
//静态方法 本身是泛型方法就行
//private static <T> T getInstance(){}
public static void main(String[] args) {
//Restrict<double>
Restrict<Double> restrict = new Restrict<>();
// if(restrict instanceof Restrict<Double>)
// if(restrict instanceof Restrict<T>)
Restrict<String> restrictString= new Restrict<>();
//返回为 true,不管你传入什么类型,它都是 Restrict类型 System.out.println(restrict.getClass()==restrictString.getClass());
System.out.println(restrict.getClass().getName());
System.out.println(restrictString.getClass().getName());
Restrict<Double>[] restrictArray;
//Restrict<Double>[] restricts = new Restrict<Double>[10];
//ArrayList<String>[] list1 = new ArrayList<String>[10];
//ArrayList<String>[] list2 = new ArrayList[10];
}
}
public class ExceptionRestrict {
/*泛型类不能extends Exception/Throwable*/
//private class Problem<T> extends Exception;
/*不能捕获泛型类对象*/
// public <T extends Throwable> void doWork(T x){
// try{
//
// }catch(T x){
// //do sth;
// }
// }
public <T extends Throwable> void doWorkSuccess(T x) throws T{
try{
}catch(Throwable e){
throw x;
}
}
}
6、泛型类型的继承规则
1、Pair<Employee>和Pair<Worker>没有任何继承关系
public class Employee {
private String firstName;
private String secondName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
}
public class Worker extends Employee {
}
public class Pair<T> {
private T one;
private T two;
public T getOne() {
return one;
}
public void setOne(T one) {
this.one = one;
}
public T getTwo() {
return two;
}
public void setTwo(T two) {
this.two = two;
}
private static <T> void set(Pair<Employee> p){
}
public static void main(String[] args) {
//Pair<Employee>和Pair<Worker>没有任何继承关系
Pair<Employee> employeePair = new Pair<>();
Pair<Worker> workerPair = new Pair<>();
Employee employee = new Worker();
//Pair<Employee> employeePair2 = new Pair<Worker>();
Pair<Employee> pair = new ExtendPair<>();
set(employeePair);
//不可以,通配符可以
//set(workerPair);
}
/*泛型类可以继承或者扩展其他泛型类,比如List和ArrayList*/
private static class ExtendPair<T> extends Pair<T>{
}
}
7、通配符类型
1、?extends Object:只能传入它自己和它的子类,限定你的上界;
2、?super Object:只能传入它自己和它的父类,限定你的下界;
//关系:Food 是父类;Fruit extends Food
// HongFuShi extends Apple; Apple extends Fruit
// Orange extends Fruit
public class WildChar{
public static void print(GenericType<Fruit> p){
System.out.println(p.getData().getColor());
}
public static void use(){
GenericType<Fruit> a = new GenericType<>();
print(a);
GenericType<Orange> b = new GenericType<>();
//print(b);
}
public static void print2(GenericType<? extends Fruit> p){
System.out.println(p.getData().getColor());
}
public static void use2(){
GenericType<Fruit> a = new GenericType<>();
print2(a);
GenericType<Orange> b = new GenericType<>();
print2(b);
//print2(new GenericType<Food>());
GenericType<? extends Fruit> c = new GenericType<>();
Apple apple = new Apple();
Fruit fruit = new Fruit();
//c.setData(apple);
//c.setData(fruit);
Fruit x = c.getData();
}
public static void printSuper(GenericType<? super Apple> p){
System.out.println(p.getData());
}
public static void useSuper(){
GenericType<Fruit> fruitGenericType = new GenericType<>();
GenericType<Apple> appleGenericType = new GenericType<>();
GenericType<HongFuShi> hongFuShiGenericType = new GenericType<>();
GenericType<Orange> orangeGenericType = new GenericType<>();
printSuper(fruitGenericType);
printSuper(appleGenericType);
// printSuper(hongFuShiGenericType);
// printSuper(orangeGenericType);
//表示GenericType的类型参数的下界是Apple
GenericType<? super Apple> x = new GenericType<>();
x.setData(new Apple());
x.setData(new HongFuShi());
//x.setData(new Fruit());
Object data = x.getData();
}
}
8、Java 虚拟机如何使用泛型:
1、泛型擦除:
注意:类型擦除之后,类型是一样的。
public class Conflict {
public static String method(List<String> stringList){
System.out.println("List");
return "OK";
}
// public static Integer method(List<Integer> stringList){
// System.out.println("List");
// return 1;
// }
/*
* Signature (弱记忆)
*
* ? super xxxx
*
* */
}
网友评论