泛型的本质:类型参数化。
一:泛型的优点:
a, 让我们少写几个类的代码,b,让我们定义安全的泛型类
二:自定义泛型类:
package gen01;
/**
* 自定义泛型类 BasicController
* @author john
*
* @param <E>
* @param <S>
*/
public class BasicController<E,S> {
private E e;
//private static S s; //泛型不能定义在静态属性上
public BasicController() {
super();
}
}
三:自定义泛型接口:
package gen01;
/**
* 泛型接口 Comparator
* @author john
*
* @param <E>
*/
public interface Comparator<E> {
//接口不能有泛型属性,因为接口的属性是静态的。
// /*public static final*/ E e;
//公共的抽象方法
/*public abstract */ E compare(E e);
}
四:自定义泛型方法:
package gen01;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 非泛型类中定义泛型方法
* @author john
*
*/
public class Method {
//自定义泛型方法
//定义: 在返回类型前加上<字母>
public static <T> void test(T t){
System.out.println(t);
}
//自定义释放资源的泛型方法
public static <T extends Closeable> void testClose(T... t){
for(T temp:t){
try {
if(null!=temp){
temp.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws FileNotFoundException {
test("自定义泛型方法测试");
testClose(new FileInputStream("G:\\aaa.txt"));
}
}
五:父类为泛型类,子类继承时:
子类为富二代
package gen02;
/**
* 泛型父类
*1,保留父类泛型,子类必须为泛型。
*2,不保留父类泛型,子类按需实现。
*
*属性及方法类型随位置而定
*子类重写方法类型 --->随父类而定
*eg: test 方法的参数
*子类使用父类的属性 --->随父类而定
*eg: this.age;
*
*子类中使用自己的属性 --->随自己而定
*eg: Child1中的 A sex;
*
* @author john
*
* @param <T1>
* @param <T2>
*/
public abstract class Father<T1,T2>{
T1 age;
public abstract void test(T2 name);
}
//保留
//1,全部保留
class Child1<T1,T2,A> extends Father<T1,T2>{
A sex;
@Override
public void test(T2 name) {
T1 t1 = this.age; //---> T1
}
}
//2,部分保留
class Child2<T2,A> extends Father<Integer,T2>{
@Override
public void test(T2 name) {
Integer tempAge = this.age; //--->Integer
}}
//不保留
//1,有具体类型
class Child3 extends Father<Integer,String>{
@Override
public void test(String name) {
Integer tempAge = this.age; //--->Integer
}
}
//2,没有具体类型 ,擦除
class Child4 extends Father{
@Override
public void test(Object name) {
Object tempAge = this.age; //--->Object
}
}
//Child4 等价于 class Child5 extends Father<Object,Object>{}
六:接口为泛型接口 实现类实现时:
同上
七:泛型擦除:
泛型擦除指使用|实现|继承的时候没有指定类型,我们称之为泛型擦除。
类似于Object, 不完全等同于Object 不指定类型编译不会自动检查,指定类型后编译会自动检查
package gen02;
/**
* 泛型擦除
* 泛型擦除指使用|实现|继承的时候没有指定类型
* 类似于Object, 不完全等同于Object 不指定类型编译不会自动检查,指定类型后编译会自动检查
*
* @author john
*/
public class MyStuApp {
public static void main(String[] args) {
MyStudent myStudent = new MyStudent<>();
myStudent.setAge(18);
Object age = myStudent.getAge();
test(myStudent);//不指定类型编译不会自动检查
MyStudent<Object> myStudent2 = new MyStudent<Object>();
//test(myStudent2);//指定类型后编译会自动检查,此处会报错
}
public static void test(MyStudent<String> student){
System.out.println(student.getAge());
}
}
class MyStudent<T>{
T age;
public T getAge() {
return age;
}
public void setAge(T age) {
this.age = age;
}
}
八:泛型通配符"?":
表示类型不确定,只能用在声明变量,不能用在定义泛型类、泛型接口、泛型方法上。
package gen03;
import java.util.ArrayList;
import java.util.List;
public class WildcardTest {
public static void main(String[] args) {
//声明
List<?> lists = new ArrayList<String>();
lists = new ArrayList<Integer>();
lists = new ArrayList<Object>();
//编译错误 通配符不能用来创建对象
//lists = new ArrayList<?>();
}
public static void test(List<?> lists){
}
//不能用在创建泛型方法 编译通不过
// public static <?> void test2(List<?> lists){
//
// }
}
//不能用在创建泛型类 编译通不过
//class Test<?>{
//
//}
九:泛型上限"extends":
一般用于限制操作,表示小于等于,即子类或自身。
不能添加数据进去的理由是:保证向下兼容一致性。
package gen03;
/**
* 继承链
* Object
* |
* Fruit
* / \
* Apple Pear
* |
* FujiApple
*
* @author john
*
*/
public class Fruit {}
class Apple extends Fruit{};
class Pear extends Fruit{};
class FujiApple extends Apple{};
package gen03;
import java.util.ArrayList;
import java.util.List;
/**
* extends 泛型上限 <= 即子类
* 1,一般使用于限制操作。
* 2,不能使用在添加数据操作 保证向下兼容一致性。
* 3,规则
*
* @author john
*/
public class ExtendsTest {
public static void main(String[] args) {
//extends 为上限
//1 泛型定义属性
Test<Fruit> test1 = new Test<Fruit>();
Test<Pear> test2 = new Test<Pear>();
Test<Apple> test3 = new Test<Apple>();
//泛型没有多态 下面这行代码编译无法通过
// Test<Apple> test4 = new Test<FujiApple>();
List<? extends Fruit> list1 = new ArrayList<Fruit>();
test(list1);
List<Fruit> list2 = new ArrayList<Fruit>();
test(list2);
List<Apple> list3 = new ArrayList<Apple>();
test(list3);
List<? extends Apple> list4 = new ArrayList<FujiApple>();
test(list4);
//? -->为什么报错 因为? 等同于 ? extends Object Object>Fruit 所以报错
List<?> list5 = new ArrayList<FujiApple>();
//test(list5);
}
//2 使用extends定义泛型方法 ? extends Fruit
public static void test(List<? extends Fruit> lists){
//lists 不能添加任何非空对象 进去的理由是:保证向下兼容一致性。
// lists.add(new Fruit());
// lists.add(new Apple());
// lists.add(new Pear());
// lists.add(new FujiApple());
// lists.add(null);
}
//泛型类
static class Test<T extends Fruit>{}
}
十:泛型下限"super":
一般用于限制操作,表示大于等于,即父类或自身。
不用用来添加父类数据进去的理由是:保证向上兼容一致性。
package gen03;
/**
* 继承链
* Object
* |
* Fruit
* / \
* Apple Pear
* |
* FujiApple
*
* @author john
*
*/
public class Fruit {}
class Apple extends Fruit{};
class Pear extends Fruit{};
class FujiApple extends Apple{};
package gen03;
import java.util.ArrayList;
import java.util.List;
/**
* extends 泛型下限 >= 即父类或自身。
* @author john
*/
public class SuperTest {
public static void main(String[] args) {
List<Fruit> list1 = new ArrayList<Fruit>();
test(list1);
List<Object> list2 = new ArrayList<Object>();
test(list2);
List<Apple> list3 = new ArrayList<Apple>();
test(list3);
List<? extends Apple> list4 = new ArrayList<Apple>();
//test(list4); //编译通不过
}
// 使用extends定义泛型方法
public static void test(List<? super Apple> lists){
//自能添加自身或者子对对象 不能添加父类对象 理由是:保证向上兼容一致性。
lists.add(new Apple());
lists.add(new FujiApple());
//lists.add(new Fruit());//编译通不过
}
}
十一:泛型嵌套:
package gen03;
/**
* 泛型嵌套
* @author john
*
*/
public class GenericQianTao {
public static void main(String[] args) {
Student<Integer> student = new Student<Integer>();
student.setScore(100);
Class<Student<Integer>> bj = new Class<Student<Integer>>();
bj.setStudent(student);
Student<Integer> stu = bj.getStudent();
System.out.println(stu.getScore());
}
}
class Student<T>{
T score;
public T getScore() {
return score;
}
public void setScore(T score) {
this.score = score;
}
}
class Class<T>{
T student;
public T getStudent() {
return student;
}
public void setStudent(T student) {
this.student = student;
}
}
JDK里面嵌套的典型应用是Map集合遍历时使用Entry时的场景。
泛型没有多态。
没有泛型数组。
jdk1.7对泛型的简化 List<String> lists = new ArrayList<>();
后面的有时间整理下 20160509。
二: 定义泛型:
a,定义单个类型持有者 UserDao<User> userDao = new UserDao<User>();
b,定义多个类型持有者 UserDao<Long,User> userDao = new UserDao<Long,User>();
三:限制泛型的可用类型(有界类型 extends super):
1, extends
a,定义类/接口
public class UserDao<T>{
...
}
与
public class UserDao<T extends Object>{
...
}
是等价的。
所以我们想用限制类型定义类的时候该写成 注意1:不能用将T换成? 程序会报错。可以定义多个类型持有者。
public class UD<T extends Fruit>{
....
}
注意2:public class/interface 父类/父接口名字<T>的子类/子接口/实现类 在继承父类/继承父接口i/实现接口中
写法最好是 public class/interface 子 类/子 接口名字 extends/implements 父 类/ 父 接口名字<User>
或者 public class/interface 子 类/子 接口名字<E extends BasicTreeEntity> extends/implements 父 类/ 父 接口名字<E>
List<? extends Fruit> list1 = new ArrayList<Fruit>();
List<? extends Fruit> list2 = new ArrayList<Apple>();
List<? extends Fruit> list3 = new ArrayList<Orange>();
//list1.add(new Fruit()); // 报错
//list2.add(new Apple()); // 报错
//list3.add(new Orange()); // 报错//list2 list3
//另外一种解释 http://blog.csdn.net/hippoppower/article/details/4473991
c,方法参数 和 返回值类型 理解这种代码的写法 以后自己写代码多用这种.
定义父类型 传参的时候可以传递父类和父类的子类进去。返回实际类型。
调用上面的方法的代码
2,super
a,定义类 没有这种写法
b,定义变量 不理解这里 也不理解这种定义的用处。
List<Fruit> fruitList2 = new ArrayList<Fruit>();
或者