java 泛型

博客介绍了Java泛型,泛型可让编译器处理细节,实现“参数化类型”,使代码适用于多种类型。还列举了简单泛型、泛型接口、泛型方法等实例,同时提及擦除与边界、通配符以及泛型存在的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型是什么?

泛型就是告诉编译器想使用什么类型,然后编译器帮你处理一切细节。泛型实现了“参数化类型”的概念,使代码可以应用于多种类型。使用泛型,我们只需指定它们的名称以及类型参数列表即可。

实例如下:

简单泛型

// 持有单个对象的类
class Automobile{} // 汽车
class Holder{ // 持有者
	private Automobile a;
	public Holder( Automobile a ){ this.a = a; }
	Automobile get(){ return a; }
}
// 持有Object类型对象的类
class Holder{
	private Object a;
	public Holder( Object o ){ this.a = a; }
	public void set( Object a ){ this.a = a; }
	public Object get(){ return a; }
	public static void main( String[] args ){
		Holder h = new Holder( new Automobile() );
		Automobile a = ( Automobile ) h.get();
		h.set( "Not an Automobile" );
		String s = ( String ) h.get();
		h.set( 1 );
		Integer x = ( Integer ) h.get();
	}
}
// 使用容器存储一种类型的对象
class Holder< T >{ // 给类加类型参数T
	private T a;
	public Holder( T a ){ this.a = a; }
	public void set( T a ){ this.a = a; }
	public T get(){ return a; }
	public static void main( String[] args ){
		Holder< Automobile > h = new Holder< Automobile >( new Automobile() ); // 只能存入T类型或其子类
		Automobile a = h.get();
		// h.set( "Not an Automobile" ); // 错误:无法应用于String
		// h.set( 1 ); // 错误:无法应用于int
	}
}

泛型接口

interface Generator< T >{ T next(); } // 生成器
class NumGenerator implements Generator< Integer >{
	int[] nums = { 1, 2, 3, 4, 5 };
	public Integer next(){
		return nums[ (int)( Math.random() * 5 ) ];
	}
	public static void main( String[] args ){
		NumGenerator num = new NumGenerator();
		for( int i = 0; i < 5; i ++ )
			System.out.println( num.next() );
	}
}
class NameGenerator implements Generator< String >{
	String[] names = { "ryan", "anni", "john" };
	public String next(){
		return names[ (int)( Math.random() * 3 ) ];
	}
	public static void main( String[] args ){
		NameGenerator name = new NameGenerator();
		for( int i = 0; i < 5; i ++ )		
			System.out.println( name.next() );
	}
}
public class Test0528{
	public static void main( String[] args ){
		NumGenerator.main( args );
		NameGenerator.main( args );
	}
}
------------------------
E:\java>java Test0528
1
2
4
1
4
anni
ryan
anni
john
anni

泛型方法

// 泛型方法:泛型参数列表放在方法定义的返回值之前。泛型方法能够独立于类而产生变化。
// 指导原则:尽量使用泛型方法。如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法。
// 类型参数推断:当使用泛型类时,必须在创建对象时指定类型参数的值。而使用泛型方法时,通常不必指明参数类型,因为编译器会为我们
// 找出具体的类型。
class GenericMethods{ // 泛型方法
	public < T > void f( T x ){ System.out.println( x.getClass().getName() );}
	public static void main( String[] args ){
		GenericMethods gm = new GenericMethods();
		gm.f( "" );  gm.f( 1 );  gm.f( 1.0 );
		gm.f( 1.0F );  gm.f( 'c' );  gm.f( gm );
	}
}
public class Test0528{
	public static void main( String[] args ){
		GenericMethods.main( args );
	}
}
----------------------
E:\java>java Test0528
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Float
java.lang.Character
GenericMethods

擦除与边界

// 擦除:在方法体中移除了类型信息。
import java.util.*;
class ErasedTypeEquivalence{ // 擦除类型等效
	public static void main( String[] args ){
		Class c1 = new ArrayList< String >().getClass();
		Class c2 = new ArrayList< Integer >().getClass();
		System.out.println( c1 );
		System.out.println( "c1 == c2 : " + (c1 == c2) ); // 都被擦除成List“原生”类型。
	}
}
public class Test0528{
	public static void main( String[] args ){
		ErasedTypeEquivalence.main( args );
	}
}
---------------------
E:\java>java Test0528
class java.util.ArrayList
c1 == c2 : true // 相同类型
import java.util.*;
class Frob{}
class Fnorkle{}
class Quark< Q >{}
class Particle< POSITION, MOMENTUM >{}
class LostInformation{ // 丢失信息
	public static void main( String[] args ){
		List< Frob> list = new ArrayList< Frob >();
		Map< Frob, Fnorkle > map = new HashMap< Frob, Fnorkle >();
		Quark< Fnorkle > quark = new Quark< Fnorkle >();
		Particle< Long, Double > p = new Particle< Long, Double >();
		// getTypeParameters()返回一个TypyVariable对象数组,表示有泛型声明所声明的类型参数
		System.out.println( Arrays.toString( list.getClass().getTypeParameters() ) );
		System.out.println( Arrays.toString( map.getClass().getTypeParameters() ) );
		System.out.println( Arrays.toString( quark.getClass().getTypeParameters() ) );
		System.out.println( Arrays.toString( p.getClass().getTypeParameters() ) );
	}
}
public class Test0528{
	public static void main( String[] args ){
		LostInformation.main( args );
	}
}
---------------------
E:\java>java Test0528
[E] // Java泛型是使用擦除来实现的。在泛型代码内部,无法获得任何有关泛型参数类型的信息。
[K, V]
[Q]
[POSITION, MOMENTUM]
// 边界:对象进入和离开方法的地点。这些正是编译器在编译期执行类型检查并插入转型代码的地点。
interface HasColor{ java.awt.Color getColor(); } // 有颜色
class HoldItem< T >{ // 保持项目
	T item;
	HoldItem( T item ){ this.item = item; }
	T getItem(){ return item; }
}
class Colored< T extends HasColor > extends HoldItem< T >{ // 彩色的
	Colored( T item ){ super( item ); }
	java.awt.Color color(){ return item.getColor(); }
}
class Dimension{ public int x,y,z; } // 尺寸
class ColoredDimension< T extends Dimension & HasColor > extends Colored< T >{ // 彩色尺寸
	ColoredDimension( T item ){ super( item ); }
	int getX(){ return item.x; }
	int getY(){ return item.y; }
	int getZ(){ return item.z; }
}
interface Weight{ int weight(); } // 重量
class Solid< T extends Dimension & HasColor & Weight > extends ColoredDimension< T >{ // 固体
	Solid( T item ){ super( item ); }
	int weight(){ return item.weight(); }
}
class Bounded extends Dimension implements HasColor,Weight{ // 有界
	public java.awt.Color getColor(){ return null; }
	public int weight(){ return 0; }
}
class InheritBounds{ // 继承界限
	public static void main( String[] args ){
		Solid< Bounded > solid = new Solid< Bounded >( new Bounded() );
		solid.color();
		solid.getY();
		solid.weight();
	}
}

通配符

// 协变性对List不直作用
import java.util.*;
class Fruit{} // 水果
class Apple extends Fruit{} // 苹果
class Jonathan extends Apple{} // 乔纳苹
class Orange extends Fruit{} // 橘子
class CovariantArray{ // 协变数组
	public static void main( String[] args ){
		Fruit[] fruit = new Fruit[10];
		fruit[0] = new Apple();
		System.out.println( fruit[0] );
		fruit[1] = new Jonathan();
		System.out.println( fruit[1] );
		try{
			fruit[0] = new Fruit();
			System.out.println( fruit[0] );
		}catch( Exception e ){ System.out.println( e ); }
		try{
			fruit[0] = new Orange();
			System.out.println( fruit[0] );
		}catch( Exception e ){ System.out.println( e ); }
	}
}
class NonCovariantGenerics{ // 非协变泛型
	public static void main( String[] args ){
		// List< Fruit > flist = new ArrayList< Apple >(); // 错误:不兼容的类型
	}
}
class GenericsAndCovariance{ // 泛型和协变性
	public static void main( String[] args ){
		List< ? extends Fruit > flist = new ArrayList< Apple >(); // 通配符
		// 不能添加任何类型的对象
		// flist.add( new Apple() ); 
		// flist.aad( new Fruit() );
		// flist.add( new Object() );
		flist.add( null );
		Fruit f = flist.get( 0 );
		System.out.println( f );
	}
}
public class Test0529{
	public static void main( String[] args ){
		CovariantArray.main( args );
		GenericsAndCovariance.main( args );
	}
}
---------------------
E:\java>java Test0529
Apple@ca0b6
Jonathan@1a758cb
Fruit@1b67f74
Orange@173a10f
null 

泛型的问题

// 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值