泛型

泛型

泛型实质就是将数据的类型参数化。
通过为类、接口和方法设置类型参数来定义泛型。

泛型类的定义:[修饰符] class 类名<T>
泛型接口的定义:[public] interface 接口名<T>
泛型方法的定义:[public] [static] <T> 返回值类型 方法名(T 参数)

泛型类及应用

public class Demo<T>{
    private T obj;
    public T getObj(){
        return obj;
    }
    public void setObj(T obj){
        this.obj = obj;
    }
    
    public static void main(String[] args){
        Demo<String> name = new Demo<String>();
        Demo<Integer> age = new Demo<Integer>();
        name.setObj("王旭");
        String newName = name.getObj();
        Ststem.out.println("姓名:"+newName);
        age.setObj(18);
        Integer newAge = age.getObj();
        Ststem.out.println("年龄:"+newAge);
    }
}

程序输出为:
姓名:王旭
年龄:18

注意,程序中getObj和setObj不是泛型方法,他只是拥有泛型的类型参数而已。在Demo类中,凡是在T出现的地方,都被String或者Integer代替。也就是说,T相当于形参,String相当于实参。

泛型方法

要定义泛型方法,只需在方法返回值类型前面添加泛型的类型参数<T>就可以了
在Java中任何方法都可以声明为泛型方法,其调用时与普通方法一样。

public class Demo {

	public static void main(String[] args) {
		Integer[] num = {1,2,3,4,5};
		String[] str = {"李","黄","许","关","张","王"}
		Demo.display(num);
		Demo.display(str);
	}
	
	public static<E> void display(E[] list) {
		for(int i=0;i<list.length;i++) {
			System.out.print(list[i]+" ");
		}
		System.out.println("");
	}

}

如果泛型方法的多少形参使用了相同的类型参数,而对应的实参具有不同类型,则编译器会该类型参数指定为多个类型实参具有的最近公共父类。

static方法无法访问泛型类的类型参数,所以如果static方法需要使用泛型能力,必须成为泛型方法。

限制泛型的可用类型

可使用这样的语法:
<T extends 类> 传入类型是指定类或者其子类
<T extends 接口> 传入类型是实现了该接口了类
例如:
public class ArrayStack<E extends Number>
public static <E extends Comparable<E>> void bubbleSort(E[] elements)

泛型通配符

考虑这样一种情况,当使用泛型类作为某个方法的形参时,如:
public static void output(Demo<__> d) {
….
}

下划线的部分应该如何填,如果只填单个类,如String的话,那么那只能传入String类型的Demo泛型类实参。
所以java引入了通配符的概念。如果为Demo<?> d,则为无边界的通配符,可以传入任意类型的Demo泛型类实参。
如果为Demo<? extends E>,则为固定上边界的通配符,可以传入E类或者其子类。
如果为Demo<? super E>,则为固定下边界通配符,可以传入E类或者其父类。

继承泛型类与实现泛型接口

1.泛型全部保留,子类为泛型子类
class F1<T1, T2> extends GenericClass<T1,T2>{
@Override public void test(T2 name) { }
}

2.泛型部分保留,部分确定类型,子类为泛型子类
class F2<T2> extends GenericClass<Integer,T2>{
    @Override public void test(T2 name) { }
}

3.不保留,全部确定具体类型,子类是非泛型类
class F3 extends GenericClass<Integer,String>{
    @Override  public void test(String name) {  }
}

4.没有类型(擦除,类似于Object),子类是非泛型类
class F4 extends GenericClass{
    @Override  public void test(Object name) {  }
}

5.子类可以增加自己的泛型
class F5<T1, T2, T3> extends GenericClass<T1,T2>{
    T3 data;
    @Override public void test(T2 name) {    }
}

7.全部或部分保留接口泛型,子类为泛型子类
class F1<T> implements GenericInterface<T>{
    @Override public void test(T para) { }
}

8. 全部确定接口泛型的具体类型,子类是非泛型类
class F2 implements GenericInterface<String>{
   @Override  public void test(String para) { }
}


jinli_

一个永远在入门的程序员

发表评论

电子邮件地址不会被公开。 必填项已用*标注