Java-泛型
-
- 一、泛型相关概念
- 二、含有泛型的类
- 三、含有泛型的方法
- 四、含有泛型的接口
-
- 1.在进行实现类的创建时,指定接口的泛型
- 2.在进行实现类的创建时,给实现类也加上泛型
- 五、泛型通配符
-
一、泛型相关概念
泛型:规定存储在集合中的所有元素的统一数据类型,尖括号<E>代表泛型,E代表
集合中所有元素的数据类型(E只是个代号,可以根据需要随意起名,例如<M>
,<T>等)
注意:
1.泛型只能是引用数据类型,不能是基本数据类型,如果想要使用基本类型,
需要使用基本类型的包装类
2.泛型可以理解为是一个变量,用于接收数据类型
为什么要使用泛型:
见下图
使用泛型和不使用泛型的区别
1.不使用泛型
好处:集合中可以存储任意数据类型对象,它们会被默认提升到Object类型
坏处:
1.当取出一个指定数据类型的对象,进行其特有的操作时,必须进行类型转换,
2.不安全,编译期(写代码时)可能不会出错,但运行期(代码运行)可能会报错。
2.使用泛型:
好处:
1.集合中存储的是同一数据类型数据,避免了类型转换。
2.把运行期异常,转换到编译期异常,编译不出错,运行就不出错
坏处:只能存储指定类型数据
public class GenericDemo01 {
public static void main(String[] args) {
Collection col1 = new ArrayList();
col1.add(1);
col1.add("abcd");
col1.add(true);
System.out.println(col1);
Iterator it1 = col1.iterator();
while(it1.hasNext()){
Object obj = it1.next();
System.out.print(obj+" ");
String str = (String)obj;
System.out.println(str.length());
}
Collection<String> col2 = new ArrayList<>();
col2.add("abc");
System.out.println(col2);
Iterator<String> it2 = col2.iterator();
while(it2.hasNext()){
String str = it2.next();
System.out.println(str.length());
}
}
}
二、含有泛型的类
使用泛型定义一个类:当一个类不确定将要使用什么数据类型,可以使用泛型
定义格式:修饰符 class 类名称<E>{
内容
}
使用格式:
类名<E> 对象名 = new 类名称<>();
public class GenericDemo02 {
public static void main(String[] args) {
GenericDemo<String> name = new GenericDemo<>();
name.setStuName("王小明");
name.setAge(10);
System.out.println(name.getStuName());
GenericDemo<Integer> name1 = new GenericDemo<>();
name1.setStuName(1);
name.setAge(10);
System.out.println(name1.getStuName());
}
}
class GenericDemo<E>{
private E stuName;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public E getStuName() {
return stuName;
}
public void setStuName(E stuName) {
this.stuName = stuName;
}
}
三、含有泛型的方法
定义含有泛型的方法
定义格式: 修饰符 <M> 返回值类型 方法名(参数列表(使用泛型)){
方法体;
}
使用格式:
在调用方法的时候进行指定类型,参数传递的是什么类型,
泛型就是什么类型
public class GenericDemo03 {
public static void main(String[] args) {
GenericDemo1 demo=new GenericDemo1();
demo.method(1);
demo.method("字符串");
demo.method(true);
GenericDemo1.method2(1);
GenericDemo1.method2("字符串");
GenericDemo1.method2(true);
}
}
class GenericDemo1{
public <M> void method(M m){
System.out.println(m);
}
public static <T> void method2(T t){
System.out.println(t);
}
}
四、含有泛型的接口
带有泛型的接口:
定义格式:
public interface 接口名<I>{
方法定义
}
使用格式:
1.在进行实现类的创建时,指定接口的泛型
格式:修饰符 class 实现类名称 implements 接口名<数据类型>{
}
例:public interface Iterator<I>{
I next();
}
public class Scanner implements Iterator<String>{
}
所以Scanner中的next方法默认返回的是字符串类型
2.在进行实现类的创建时,给实现类也加上泛型,但是需要和接口保持一致
格式:修饰符 class 实现类名称<I> implements 接口名<I>{
}
1.在进行实现类的创建时,指定接口的泛型
public interface Generic<T> {
public void method(T t);
}
public class GenericDemo04 implements Generic<String>{
@Override
public void method(String t) {
System.out.println(t);
}
}
public class GenericDemo05 {
public static void main(String[] args) {
GenericDemo04 g = new GenericDemo04();
g.method("字符串");
}
}
2.在进行实现类的创建时,给实现类也加上泛型
public interface Generic<T> {
public void method(T t);
}
public class GenericDemo06<T> implements Generic<T> {
@Override
public void method(T t) {
System.out.println(t);
}
}
public class GenericDemo07 {
public static void main(String[] args) {
GenericDemo06<String> g = new GenericDemo06<>();
g.method("字符串");
GenericDemo06<Integer> i = new GenericDemo06<>();
i.method(2);
}
}
五、泛型通配符
1.泛型通配符
泛型通配符:
在不知道泛型类和泛型接口中传递的是什么数据,可以使用泛型通配符<?>,?可以表示任意数据类型
一旦使用泛型通配符,只能使用Object类中的共性方法,不能使用集合元素的特有方法
泛型通配符只能接收数据,不能向集合中存储数据,
与之前的区别:
之前的泛型必须先定义才能使用,泛型通配符已经存在,可以直接
使用
使用方式
1.不能创建对象使用,
2.只能作为方法参数使用
注意:泛型没有继承的概念
ArrayList<Object> obj = new ArrayList<String>();
public static void method(Collection<?> al){
Iterator it1 =al.iterator();
while(it1.hasNext()){
Object obj = it1.next();
System.out.print(obj+" ");
}
}
}
2.泛型通配符高级使用
通配符的高级使用--受限泛型 (了解即可)
泛型上限限定:? extends E 使用的泛型只能是E类型的子类或者本身
泛型下限限定:? super E 使用的泛型只能是E类型的父类或者本身
public class GenericDemo09 {
public static void main(String[] args) {
Collection<Integer> col1 = new ArrayList<>();
Collection<String> col2 = new ArrayList<>();
Collection<Number> col3 = new ArrayList<>();
Collection<Object> col4 = new ArrayList<>();
}
public static void method1(Collection<? extends Number> col){
}
public static void method2(Collection<? super Number> col){
}
}