泛型简介
Java泛型是J2 SE1.5中引入的一个新特性
泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的。
泛型的原理就是 “类型的参数化”,即把类型看做参数。也就是说把所要操作的数据类型看做参数,就像方法的形式参数一样,是运行时传递的值的占位符一样。
简单的说,类型变量扮演的角色就如同一个参数,它提供给编译器用来类型检查的信息。
泛型可以提高代码的扩展性和重用性。
class Cls1 <T> //定义泛型类
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Integer> cls1 = new Cls1<Integer>(20); //使用泛型类
System.out.println(cls1.getData());
Cls1<String> cls2 = new Cls1<String>("木易");
System.out.println(cls2.getData());
}
}
泛型类及特点
泛型的类型参数可以是泛类型
class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Cls1<Integer>> cls1 = new Cls1<Cls1<Integer>>(new Cls1<Integer>(20));
System.out.println(cls1.getData().getData());
}
}
执行结果:
泛型类可以同时设置多个类型参数
class Cls2 <T,T2>
{
T a;
T2 b;
public Cls2(T a,T2 b){
this.a = a;
this.b = b;
}
public T getData(){
return a;
}
public T2 getData2(){
return b;
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls3 = new Cls2<Integer,String>(500,"wang");
System.out.println(cls3.getData());
System.out.println(cls3.getData2());
System.out.println(cls3.getData()+cls3.getData2());
Cls2<Integer,Integer> cls4 = new Cls2<Integer,Integer>(500,20);
System.out.println(cls4.getData()+cls4.getData2());
}
}
执行结果:
泛型类可以继承泛型类
class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
class Cls2 <T,T2> extends Cls1<T>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Cls1<Integer>> cls1 = new Cls1<Cls1<Integer>>(new Cls1<Integer>(20));
System.out.println(cls1.getData().getData());
Cls2<Integer,String> cls = new Cls2<Integer,String>(40,"zhang");
System.out.println(cls.getData()+" "+cls.getData2());
}
}
执行结果:
继承抽象类:
abstract class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printinfo();
}
class Cls2 <T,T2> extends Cls1<T>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
void printinfo() {
// TODO Auto-generated method stub
System.out.println("输出");
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls = new Cls2<Integer,String>(40,"zhang");
System.out.println(cls.getData()+" "+cls.getData2());
cls.printinfo();
}
}
执行结果:
泛型类可以实现泛接口
abstract class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printinfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2 <T,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
void printinfo() {
// TODO Auto-generated method stub
System.out.println("输出");
}
public void printInfoCls3(Object t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String,String> cls = new Cls2<Integer,String,String>(80,"木易");
System.out.println(cls.getData()+" "+cls.getData2());
cls.printinfo();
cls.printInfoCls3("测试");
}
}
执行结果:
限制泛型可用类型
在定义泛型类别时,默认在实例化泛型的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义该类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。
当没有指定泛类型继承的类型或接口时,默认使用extends Object,所以默认情况下任何类型都可以做为参数传入
限定泛类型只能是String:
abstract class Cls1 <T extends String> //限定泛类型T只能是String
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printinfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2 <T extends String,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
void printinfo() {
// TODO Auto-generated method stub
System.out.println("输出");
}
public void printInfoCls3(Object t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<String,String,String> cls = new Cls2<String,String,String>("muyi","木易");
System.out.println(cls.getData()+" "+cls.getData2());
cls.printinfo();
cls.printInfoCls3("测试");
}
}
执行结果:
限定泛类型只能继承类:
class Animal
{
}
class Dog extends Animal
{
}
abstract class Cls1 <T extends Animal>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printinfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2 <T extends Animal,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
void printinfo() {
// TODO Auto-generated method stub
System.out.println("输出");
}
public void printInfoCls3(Object t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<Dog,String,String> cls = new Cls2<Dog,String,String>(new Dog(),"木易");
System.out.println(cls.getData()+" "+cls.getData2());
cls.printinfo();
cls.printInfoCls3("测试");
}
}
限定泛类型只能继承某个接口:
interface Move
{
abstract void test();
}
abstract class Cls1 <T extends Move>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printinfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2 <T extends Move,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);
this.b = b;
}
public T2 getData2(){
return b;
}
void printinfo() {
// TODO Auto-generated method stub
System.out.println("输出");
}
public void printInfoCls3(Object t) {
// TODO Auto-generated method stub
System.out.println(t);
a.test();
}
}
public class Test {
public static void main(String[] args) {
Move a = new Move() {
public void test() {
// TODO Auto-generated method stub
System.out.println("test");
}
};
Cls2<Move,String,String> cls = new Cls2<Move,String,String>(a,"木易");
a.test();
cls.printInfoCls3("测试");
}
}
执行结果:
泛型通配声明
同一泛类型,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值。
Generic < Boolean > f1 = new Generic < Boolean >();
Generic < Integer> f2 = new Generic < Integer >();
f1 = f2 //会发生编译错误
Generic < Object> f = f1; //f1和f类型并不兼容,发生编译错误
f = f2; //f2和f类型同样不兼容,也会发生编译错误
泛类型实例之间的不兼容性会带来使用的不便。所以可以使用泛型通配符(?)声明泛型类的变量就可以解决这个问题。
泛型统配的方式
- “ ? ”任意一个类型
Generic < Boolean > f1 = new Generic < Boolean >();
Generic < ? > f = f1;
class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Integer> c1 = new Cls1<Integer>(20);
Cls1<Double> c2 = new Cls1<Double>(10.3);
Cls1<?> c3;
c3 = c1;
c3 = c2;
}
}
- 和限制泛类型的上限相似,同样可以使用extends关键字限定通配类型的上限
Generic < Dog> f1 = new Generic < Dog >();
Generic < ? extends Animal > f = f1;
class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Integer> c1 = new Cls1<Integer>(20);
Cls1<? extends Integer> c3;
c3 = c1;
}
}
类
class Animal
{
}
class Dog extends Animal
{
}
class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Dog> c1 = new Cls1<Dog>(new Dog());
Cls1<? extends Animal> c3;
c3 = c1;
}
}
- 可以使用super关键字将通配符匹配类型限定为某个类型
Generic < Animal > f1 = new Generic < Animal >();
Generic < ? super Dog > f = f1;
class Animal
{
}
class Dog extends Animal
{
}
class Cls1 <T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Dog> c1 = new Cls1<Dog>(new Dog());
Cls1<? super Dog> c3;
c3 = c1;
}
}
泛型方法
不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。
定义:
访问修饰符 < 泛型列表 > 返回类型 方法名 ( 参数列表 ) {
实现代码
}
在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明。
类中其它方法不能使用当前方法声明的泛型
注意:是否拥有泛方法,与其所在的类是否泛型没有关系。要定义泛方法,只需将泛型参数列表置于返回值前。
泛型方法使用场景
添加类型约束只作用于一个方法的多个参数之间、而不涉及到类中的其它方法时。
施加类型约束的方法为静态方法,只能将其定义为泛方法,因为静态方法不能使用其所在类的类型参数
基础泛应用:
class A<T>
{
public void printInfo(T t){
System.out.println(t);
}
}
class B
{
//泛型方法
public <T> void printInfo(T t){
System.out.println(t);
}
//泛型方法的重载
public <T,T2> void printInfo(T t,T2 t2){
System.out.println(t);
System.out.println(t2);
}
//方法的重载
public void print1(int a){
System.out.println(a);
}
public void print1(char a){
System.out.println(a);
}
public void print1(String a){
System.out.println(a);
}
}
public class Test {
public static void main(String[] args) {
A<String> a = new A<String>();
a.printInfo("木易");
B b = new B();
b.printInfo("yang");
b.printInfo(123);
b.printInfo(5.8);
b.printInfo('b');
b.printInfo("小黄", 180);
b.print1('r');
b.print1(20);
b.print1("天哭");
}
}
执行结果:
限制约束泛型方法:
class Animal
{
public void eat(){
System.out.println("动物吃");
}
}
class Dog extends Animal
{
public void eat(){
System.out.println("狗啃骨头");
}
}
class Cat extends Animal
{
public void eat(){
System.out.println("猫吃鱼");
}
}
class B
{
//泛型方法
public <T> void printInfo(T t){
System.out.println(t);
}
//泛型方法的重载
public <T,T2> void printInfo(T t,T2 t2){
System.out.println(t);
System.out.println(t2);
}
public <T extends Animal> void printInfo2(T t){
t.eat();
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.printInfo("yang");
b.printInfo(123);
b.printInfo(5.8);
b.printInfo('b');
b.printInfo("小黄", 180);
b.printInfo2(new Dog());
b.printInfo2(new Cat());
b.printInfo2(new Animal());
}
}
执行结果:
静态方法应用:
class Animal
{
public void eat(){
System.out.println("动物吃");
}
}
class Dog extends Animal
{
public void eat(){
System.out.println("狗啃骨头");
}
}
class Cat extends Animal
{
public void eat(){
System.out.println("猫吃鱼");
}
}
class B
{
public static <T extends Animal> void printInfo2(T t){
t.eat();
}
}
public class Test {
public static void main(String[] args) {
B.printInfo2(new Dog());
B.printInfo2(new Cat());
B.printInfo2(new Animal());
}
}
执行结果: