第 23 章 Java泛型(随笔)

1.概念

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

应用场景

假定我们有这样一个需求:写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

答案是可以使用 Java 泛型

使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序。

java 中泛型标记符:

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(Java 类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  •  - 表示不确定的 java 类型

 2.泛型的使用

使用泛型方法打印不同类型的数组元素。

public class GenericMethodTest
{
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] )
    {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

结果:
整型数组元素为:
1 2 3 4 5 

双精度型数组元素为:
1.1 2.2 3.3 4.4 

字符型数组元素为:
H E L L O 

有界的类型参数:

可能有时候,你会想限制那些被允许传递到一个类型参数的类型种类范围。例如,一个操作数字的方法可能只希望接受Number或者Number子类的实例。这就是有界类型参数的目的。

要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。

实例

下面的例子演示了"extends"如何使用在一般意义上的意思"extends"(类)或者"implements"(接口)。该例子中的泛型方法返回三个可比较对象的最大值。

实例
public class MaximumTest
{
   // 比较三个值并返回最大值
   public static <T extends Comparable<T>> T maximum(T x, T y, T z)
   {                     
      T max = x; // 假设x是初始最大值
      if ( y.compareTo( max ) > 0 ){
         max = y; //y 更大
      }
      if ( z.compareTo( max ) > 0 ){
         max = z; // 现在 z 更大           
      }
      return max; // 返回最大对象
   }
   public static void main( String args[] )
   {
      System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
                   3, 4, 5, maximum( 3, 4, 5 ) );
 
      System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
                   6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
 
      System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
         "apple", "orange", maximum( "pear", "apple", "orange" ) );
   }
}

结果:
3, 4 和 5 中最大的数为 5

6.6, 8.8 和 7.7 中最大的数为 8.8

pear, apple 和 orange 中最大的数为 pear

3.泛型类

泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。

和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

泛型类的定义格式:
修饰符 class 类名<代表泛型的变量> {  }

怕你不清楚怎么使用,这里我还是做了一个简单的泛型类:
/**
 * @param <T> 这里解释下<T>中的T:
 *           此处的T可以随便写为任意标识,常见的有T、E等形式的参数表示泛型
 *           泛型在定义的时候不具体,使用的时候才变得具体。
 *           在使用的时候确定泛型的具体数据类型。即在创建对象的时候确定泛型。
 */
public class GenericsClassDemo<T> {
 //t这个成员变量的类型为T,T的类型由外部指定
 private T t;
​
 //泛型构造方法形参t的类型也为T,T的类型由外部指定
 public GenericsClassDemo(T t) {
 this.t = t;
    }
​
 //泛型方法getT的返回值类型为T,T的类型由外部指定
 public T getT() {
 return t;
    }
}
泛型在定义的时候不具体,使用的时候才变得具体。在使用的时候确定泛型的具体数据类型。即:在创建对象的时候确定泛型。

例如:Generic<String> genericString = new Generic<String>("helloGenerics");
此时,泛型标识T的类型就是String类型,那我们之前写的类就可以这么认为:
public class GenericsClassDemo<String> {
 private String t;
​
 public GenericsClassDemo(String t) {
 this.t = t;
    }
​
 public String getT() {
 return t;
    }
}
当你的泛型类型想变为Integer类型时,也是很方便的。直接在创建时,T写为Integer类型即可:
Generic<Integer> genericInteger = new Generic<Integer>(666);

4.泛型方法

即在调用方法的时候指明泛型的具体类型。

定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){  }

例如:
/**
 *
 * @param t 传入泛型的参数
 * @param <T> 泛型的类型
 * @return T 返回值为T类型
 * 说明:
 *   1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
 *   2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
 *   3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
 *   4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E等形式的参数常用于表示泛型。
 */
 public <T> T genercMethod(T t){
 System.out.println(t.getClass());
 System.out.println(t);
 return t;
    }

调用方法时,确定泛型的类型
public static void main(String[] args) {
 GenericsClassDemo<String> genericString = new GenericsClassDemo("helloGeneric"); 
//这里的泛型跟下面调用的泛型方法可以不一样。
​
 String str = genericString.genercMethod("hello");//传入的是String类型,返回的
也是String类型
 Integer i = genericString.genercMethod(123);//传入的是Integer类型,返回的
也是Integer类型
}

这里我们可以看下结果:
class java.lang.String
hello
class java.lang.Integer
123
这里可以看出,泛型方法随着我们的传入参数类型不同,他得到的类型也不同。泛型方法能使方法独立
于类而产生变化。

5.泛型接口

泛型接口与泛型类的定义及使用基本相同。

1、定义类时确定泛型的类型
public class GenericsImp implements GenericsInteface<String> {
 @Override
 public void add(String s) {
 System.out.println("设置了泛型为String类型");
    }
}

2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型
public class GenericsImp<T> implements GenericsInteface<T> {
 @Override
 public void add(T t) {
 System.out.println("没有设置类型");
    }
}

确定泛型:
public class GenericsTest {
 public static void main(String[] args) {
 GenericsImp<Integer> gi = new GenericsImp<>();
 gi.add(66);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值