Java之泛型

       泛型呢,一般在编程语言里是可以加快程序运行速度的,但是在Java中呢,并没有什么用,并不会加速程序的运行,那不是多余的吗?当然不是,存在即合理,下面开始说一说Java的泛型。 

       Java中呢,泛型的好处就是:1.编译期进行类型检查 ; 2.类型不确定时使用。

        那怎么用呢,或是为什么是编译期的类型检查呢?接下来举

/**示例:泛型类和通配符*/
//   形式  类型参数 
//这个T 也可以换成别的字母,但是一般有个规范
       Type     T
       Element  E
       Key      K
       Value    V
class Point<T>{
	private T x;
	private T y;
	public T getX() {
		return x;
	}
	public void setX(T x) {
		this.x = x;
	}
	public T getY() {
		return y;
	}
	public void setY(T y) {
		this.y = y;
	}
	
}
public class TestPoint {

	public static void main(String[] args) {
		//这里你定义成Integer类 对应上边所有,即传入参数也要用int的
		Point<Integer> p1 = new Point<>();
		p1.setX(11);//int -> Integer->Object
		p1.setY(22);
		System.out.println(p1.getX()+","+p1.getY());
		
		Point<Double> p2 = new Point<>();
		p2.setX(11.1);// double -> Double ->Object
		p2.setY(22.2);
		System.out.println(p2.getX()+","+p2.getY());
		
		Point<String> p3 = new Point<>();
		p3.setX("11.1");//String -> Object
		p3.setY("22.2");
		System.out.println(p3.getX()+","+p3.getY());
		// 类型《具体的类型参数》 参数化类型
//		Point<Integer> p4 = new Point<Integer>();
		//类型推断    菱形语法
		Point<Object> p4 = new Point<>();
		p4.setX(11);
		p4.setY(22);
		Integer x = (Integer)p4.getX();
		Integer y = (Integer)p4.getY();
		System.out.println(x + "," + y);
		//P1 ->Integer p2->Double p3->String p4 ->Object
		TestPoint t = new TestPoint();
		t.show2(p4);
		System.out.println("----------------------------------");
		Class c1 = p1.getClass();
		Class c2 = p2.getClass();
		System.out.println(c1);
		System.out.println(c2);
		System.out.println(c1 == c2);
		//---------------------------------------------------------
	}
	public void show3(Point<String> ps,Point<? extends Object> po) {
	     po = ps;
	}
	//任意 ? 通配符 这里  后边再详细说通配符
	public void show(Point<?> p) {
		System.out.println(p.getX() + ":" + p.getY());
	}
	//只限制 为数值  
	public void show1(Point<? extends Number> p) {
		System.out.println(p.getX() + ":" + p.getY());
	}
	public void show2(Point<? super Number> p) {
		System.out.println(p.getX() + ":" + p.getY());
	}
}

接口能用吗?

 

/**示例:类型参数上限*/
interface Info1{}
interface Info2{}
class Base{}
class Sub extends Base implements Info1,Info2{}
//可以指定多个上限 ,可以是 类 也可以是接口
class Point1<T extends Base & Info1 & Info2>{
	private T x;
	private T y;
	public T getX() {
		return x;
	}
	public void setX(T x) {
		this.x = x;
	}
	public T getY() {
		return y;
	}
	public void setY(T y) {
		this.y = y;
	}
}
public class TestPoint1 {

	public static void main(String[] args) {
		Point1<Sub> p1 = new Point1<>();
		

	}

}

再来看一个:

class Point2<T>{
	private T x;
	private T y;
	//泛型构造器  如果前边不加声明 就会报错
	<E> Point2(E e){
		System.out.println(e);
	}
	public T getX() {
		return x;
	}
	public void setX(T x) {
		this.x = x;
	}
	public T getY() {
		return y;
	}
	public void setY(T y) {
		this.y = y;
	}
	
}
public class TestPoint2 {
	public static void main(String[] args) {
		//类型推断 根据参数推断
		Point2<String> p = new Point2<>(11);
		
		Point2<String> p1 = new <Integer>Point2<String>(22);

	}

}

泛型方法定义:

class Demo{
	//泛型方法定义
	public <T> void f(T t) {
		System.out.println(t);
	}
	public <T extends Object> T ff(T t) {
		//调用了泛型方法
		//类型推断
		f("hello");
		//显示指定具体的类型时  必须 用对象调用
		this.<String>f("hellotom");
		return t;
	}
}
public class TestPoint3 {

	public static void main(String[] args) {
		Demo d = new Demo();
		//类型推断,根据参数推断
		d.f("hello");
		d.f(22);
		//
		d.<String>f("hellotom");
		d.<Double>f(22.2);
	}

}

那么 子类能继承父类的泛型吗?也是不能的,泛型只存在于编译期,在运行阶段就擦除了,所以 如下,方法重载的问题也是要注意的。 

class Demo1{
	//能方法重载吗?????不能
	public void f(Point<String> p) {}//Point t
//	public void f(Point<Integer> p) {}
	<T> void f(T t) {}// Object t
	<T extends Number> void f(T t) {}// Number t
	<T extends Base & Info1> void f(T t) {}// Base t
	<T extends Info1 & Info2> void f(T t) {}// Info1 t
	
}
class Parent{
	//父类擦除后 与 子类参数相同
	public void f(Point<String> p) {}// Point p
}
class Child extends Parent{
	@Override
	public void f(Point p) {}
}
public class TestPoint4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

泛型接口,

//泛型接口
interface IA<T>{
	void af(T t);
}
//1.能确定类型
class IAImpl1 implements IA<String>{
	@Override
	public void af(String t) {
		System.out.println(t);
	}	
}
//2.不能确定接口类型
class IAImpl2<T> implements IA<T>{
	@Override
	public void af(T t) {
		System.out.println(t);
	}
	
}
public class TestPoint5 {
	public static void main(String[] args) {
		IAImpl2<Integer> ia = new IAImpl2<>();
		ia.af(34);
		IAImpl2<String> ia1 = new IAImpl2<>();
		ia1.af("abc");
	}

}

 

 

其实觉得泛型只是起到了检查作用,需要注意的就是 泛型的特性,就是会擦除,字节码文件中是没有泛型的存在的,这也是为什么用到了泛型,却并没有加速程序的运行,另外就是 通配符和 类型参数的区别。

类型参数 与 通配符的区别:

1.类型参数 可以表示一种类型;
  通配符不能 表示一种类型;
2.类型参数 只能指定 上限;
  通配符 可以指定上限 也可以指定下限;
3.类型参数 可以指定 多个上限;
  通配符只能指定一个上限。

 

 

擦除的规则:
 1.参数化类型
   Point<String>
   擦除后 为 原生类型
   Point
 2.类型参数
   1)无界类型参数,擦除后 为 Object
   class Point<T>
   <T> void f(T t){}
   2)有一个上限
     用上限替换
   3)有多个上限
     用第一个上限来替换

这是比较重要的,另外就是两种写法要注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值