详谈JAVA泛型

泛型

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

下面通过一个示例比较:

import java.util.ArrayList;
import java.util.List;

public class demo06 {
	public static void main(String[] args) {
		List list=new ArrayList();
		list.add(100);
		list.add("帅帅哒");
		for (Object object : list) {
			System.out.println(object);
		}
		System.out.println(list.get(0)+list.get(1));	//未对参数类型 java.lang.Object, java.lang.Object 定义运算符 +
		
		/*使用泛型*/
		List<String> list2=new ArrayList<String>();
		list2.add(100);	//编译报错
		list2.add("帅帅哒");
	}
}

分析:
1.上面的代码是没有使用泛型的,我们可以看到,简单的遍历是可以运行的,因为Object是所有类的父类,所以没有问题。但是一旦你要运行其他操作,类似与“+”.“-”之类的操作代码就会报错,因为没有定义。
2.本身list集合加入的类型也不一样,第一次加入的是Integer对象,第二次加入的String对象,本身就很容易出错,尤其在实际项目 开发中
3.然而下面的代码就是采用了泛型 “List< String>”也就是规定了集合中只能放入String对象,而不能放入其他对象,所以后面加入100,编译会出错。

自定义泛型

泛型类:

泛型类型用于泛型定义中的,称为泛型类

下面见代码:

public class demo06 {
	public static void main(String[] args) {
		Person person=new Person();
		System.out.println(person+"\t"+person.getname());
		Person person2=new Person(100);
		System.out.println(person2+"\t"+person2.getname());
		Person person3=new Person("帅帅哒");
		System.out.println(person3+"\t"+person3.getname());
		person3.setname(520);
		System.out.println(person3+"\t"+person3.getname());
	}
}

class Person<T>{
	
	private T name;
	
	public Person() {
		// TODO 自动生成的构造函数存根
	}
	
	public Person(T name) {
		this.name=name;
	}
	
	public T getname() {
		return name;
	}
	
	public void setname(T name) {
		this.name=name;
	}
}

以下是输出结果:
Person@15db9742 null
Person@6d06d69c 100
Person@7852e922 帅帅哒
Person@7852e922 520

分析:

1.泛型类中的成员变量默认初始化是null
2.当使用泛型的时候,可以传递任意对象,并且修改也可以使用任意对象


泛型接口:

public class demo06{
	public static void main(String[] args) {
		text1<Integer> t1=new text1();
		t1.add(100);
		text1<String> t2=new text1();
		t2.add("帅气");
		
		//text2<Integer> t3=new text2();		//编译会出错,因为你已经确定了类继承的泛型类型
		
		text2 t4=new text2();
		t4.add("帅帅哒");
		
	}
}

interface Person<T>{
	void add(T t);
}

class text1<T> implements Person<T>{
	
	@Override
	public void add(T t) {
		// TODO 自动生成的方法存根
		System.out.println("我是:"+t);
	}	
}

class text2 implements Person<String>{

	@Override
	public void add(String t) {
		// TODO 自动生成的方法存根
		System.out.println("我是:"+t);
	}		
}

输出结果:
我是:100
我是:帅气
我是:帅帅哒

分析:

1.如果类继承泛型接口的时候,没有确定类型,那么类也必须带上泛型类型,否则会编译出错
2.如果没有确定泛型接口的类,也差不多类似与泛型类
3.确定了泛型接口的类,那么也就是固定一个类型
4.泛型接口主要用于生产器,定义一个接口,所有类型都可以继承


泛型方法:

返回类型前面使用泛型字母

见下面代码:

public class demo06 {
		public static void main(String[] args) {
			Person person=new Person(100);
			System.out.println(person.getname());
			System.out.println(person.setname(new Person("帅帅哒")));
		}
	}
	
	class Person<T>{
		
		private T name;
		
		public Person(T name) {
			this.name=name;
		}
		
		public <T>T setname(Person<T> person) {
			return person.getname();
		}
		
		public T getname() {
			return name;
		}
	}

输出如下:
100
帅帅哒

分析:

1.泛型方法的定义 :必须在方法返回值前加上泛型字符,否则不算泛型方法
2.泛型方法可以定义其他类型的泛型,与本身类中的泛型定义不一样


泛型通配符:

public class demo06 {
		public static void main(String[] args) {
			
			Person<String> person=new Person("帅帅哒");
			Person<Integer> person2=new Person<Integer>(520);
			person.readName(person);
			person.readName(person2);	//类型 Person<String> 中的方法 readName(Person<String>)对于参数(Person<Integer>)不适用
			
			person.readName1(person2);
		}
	}
	
	class Person<T>{
		
		private T name;
		
		public Person(T name) {
			this.name=name;
		}
		
		public void readName(Person<T> person) {
			System.out.println(person.name);
		}
		
		public void readName1(Person<?> person) {
			System.out.println(person.name);
		}
	}

分析:

1. ?代表未知类型,类型参数赋予不确定值,任意类型
2.只能用在声明类型、方法参数上,不能用在定义泛型类上
3.在List集合定义的时候使用?,便可以new存放任意类型的集合


泛型的上下边界:

public class demo06 {
		public static void main(String[] args) {
			text<person> t1=new text<person>();
			text<SupperPeople> t2=new text<SupperPeople>();
			text<Student> t3=new text<Student>();
			t1.name(t1);
			t2.name(t2);
			t3.name(t3);
			t1.name1(t1);
			t2.name1(t2);
			t3.name1(t3);
		}
	}

	class text<T>{
		void name(text <? extends person> t) {
			System.out.println("我是学生");
		}
		void name1(text<? super person> t) {
			System.out.println("我是超人");
		}
	}

	class SupperPeople{
		
	}
	
	class person extends SupperPeople{
		
	}
	
	class Student extends person{
		
	}

代码输出:
t2.name(t2);
t3.name1(t3);
这两行代码报错,因为不符合约束条件

分析:

1.<? extends person>是表示传入的参数是person的的子类或者本身才可以运行
2.<? super person>是表示传入的参数是person的父类或者本身才可以运行


总结:

1.泛型只是编译的时候执行,实际运行中不会看到泛型,也就是看似类型不一样,实际上是一个类型
2.泛型字符一般有T、E、V、K,其中如果不够用,可以后面加数字,例如:T1、T2、T3
3.泛型目前更多的使用是在集合之中,具体的了解还需要多实践
4.有关泛型的继承、嵌套以及静态泛型没有介绍,可自行百度了解

猜你喜欢

转载自blog.csdn.net/qq_37871033/article/details/86533555