import java.util.ArrayList;
public class Generic_01 {
public static void main(String[] args) {
//当如下写时,arraylist中存放的元素只能是Dog类型
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("Mary",22));
arrayList.add(new Dog("Sam",18));
arrayList.add(new Dog("Jone",15));
//当遍历的时候,可以直接取出Dog类型,而不是Object类型。少了向下转型的转换。
for (Dog dog:arrayList){
System.out.println(dog.getAge()+" "+dog.getName());
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
22 Mary
18 Sam
15 Jone
Process finished with exit code 0
泛型的好处是
1、编译时,检查添加元素的类型,提高了安全性。
2、减少了类型转换的次数,提高效率。
泛型的作用可以在类声明时通过一个标识表示类中某个属性的类型,或者某个方法返回值的类型,或者是参数类型。
public class Generic_02 {
public static void main(String[] args) {
Person<String> stringPerson = new Person<String>("名字");
}
}
class Person<E>{
//用E表示s的数据类型,该数据类型是在创建person对象的时候指定的。在编译期间确定的。
E s;
public Person(E s) {
this.s = s;
}
public E function(){
return s;
}
}
注意E不代表值,而是表示类型。任意字母都是可以的。像T、E、G。注意放的时候只能是引用数据类型,放入基本数据类型会报错。
案例:创建3个学生对象,放入到HashSet中学生对象。放入到HashMap中,要求Key是String name,Value是学生对象。
import java.util.*;
public class Generic_03 {
public static void main(String[] args) {
HashSet<Student> hashSet = new HashSet<Student>();
hashSet.add(new Student("Mary",18));
hashSet.add(new Student("Sam",22));
hashSet.add(new Student("Tom",25));
for (Student student:hashSet){
System.out.println(student.getAge()+" "+student.getName());
}
HashMap<String,Student> hashMap = new HashMap<String,Student>();
hashMap.put("Tom",new Student("Tom",22));
hashMap.put("Tony",new Student("Tom",18));
hashMap.put("Amy",new Student("Amy",25));
Set<Map.Entry<String,Student>> entries = hashMap.entrySet();
Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Student> next = iterator.next();
System.out.println(next.getKey()+" "+next.getValue());
}
}
}
class Student{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
25 Tom
22 Sam
18 Mary
Tony Student@1540e19d
Tom Student@677327b6
Amy Student@14ae5a5
Process finished with exit code 0
public class Generic_04 {
public static void main(String[] args) {
Pig<A> aPig = new Pig<A>(new A());
Pig<A> aPig1 = new Pig<A>(new B());//由于B类继承了A类,所以在这里是B类是没有问题的。
}
}
class A{}
class B extends A{}
class Pig<E>{
E s;
public Pig(E s) {
this.s = s;
}
}
在实际开发中,往往可以简写,也是推荐的写法,就是等号右边尖括号中可以不写内容。如果没有指定类型,默认的泛型是Object。
自定义泛型就是自己写的一个类或者接口,在后面加上泛型。
注意:
1、属性和方法可以使用泛型
2、使用泛型的数组是不能初始化的。
3、静态属性、静态方法中不能使用类的泛型。
4、泛型类的类型,是在创建对象的时候确定的。
5、如果创建对象时,没有指定类型,则默认是Object。
public class Generic_05 {
public static void main(String[] args) {
}
}
//自定义泛型
class Employee<T,G,E>{
public String name;
T t;
G g;
E e;
public Employee(String name, T t, G g, E e) {
this.name = name;
this.t = t;
this.g = g;
this.e = e;
}
}
语法:
interface 接口名<T、R>{
}
注意:
1、在接口中,静态成员也不能使用泛型。
2、泛型接口的类型,在继承接口或者实现接口时确定。
3、没有指定类型,则默认是Object类型。
基本语法
修饰符 <T、R> 返回类型 方法名(参数列表){
}
泛型方法可以定义在普通类中,也可以定义在泛型类中。
在泛型方法被调用的时候,确定泛型类型。
public class Generic_07 {
public static void main(String[] args) {
Car car = new Car();
//当调用方法时,传入参数,编译器就会确定类型。
car.m1("名字",100);
car.m1(100,"String");
}
}
class Car{
public<T,E> void m1(T t,E e){
System.out.println(t.getClass());
System.out.println(e.getClass());
}
}
注意区分泛型方法和方法使用了泛型。
泛型不具备继承性。
<?> 支持任意泛型类型 <? extends A> 支持A类以及A类的子类,规定了泛型的上限。 <? super A>支持A类以及A类的父类,不限于直接父类,规定了泛型的下限。