2021-09-07-泛型

目录

1、什么是泛型

2、自定义栈  

3、泛型方法

4、通配泛型

5、消除泛型对泛型的限制

6、对泛型的限制

7、泛型矩阵类

1、什么是泛型

        泛型是JDK1.5推出的新特性,java允许定义泛型类、泛型接口和泛型方法。Java API中的一些类和接口使用泛型进行了修改。Java 泛型的参数只可以代表类,不能代表个别对象。由于Java泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型,而且无法直接使用基本值类型作为泛型类型参数。Java编译程序在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。     

2、自定义栈  

        通过ArrayList封装泛型,模拟栈是否存在,栈的空间大小,push():压栈,pop():出栈:回栈顶的值之后将栈顶元素进行删除。peek():返回栈顶报留栈元素

import java.util.ArrayList;
/**
 * 自定义栈,支持泛型
 * 
 * @param <T> 类型化参数,在使用过程中,传递一个具体的类型替代它
 */
public class GenericStack<T> {
	private ArrayList<T> stack = new ArrayList<>();
	
	
	public boolean isEmpty() {
		return stack.isEmpty();
	}
	
	
	public int size() {
		return stack.size();
	}
	
	public void push(T element) {
		stack.add(element);
	}
	
	public T pop() {
		return stack.remove(size() - 1);
	}
	
	public T peek() {
		return stack.get(size() - 1);
	}
	
}

3、泛型方法

public class GenericMethodDemo {
  public static void main(String[] args ) {
    Integer[] integers = {1, 2, 3, 4, 5};
    String[] strings = {"London", "Paris", "New York", "Austin"};
    GenericMethodDemo.<Integer>print(integers);//或者print(integers);
    GenericMethodDemo.<String>print(strings);//或者print(strings);实际类型没有明确指定。编译器自动发现实际类型
  }

  public static <E> void print(E[] list) {
    for (int i = 0; i < list.length; i++)
      System.out.print(list[i] + " ");
    System.out.println();
  }
}

4、通配泛型

        ?称为非受限通配(unbounded wildcard),它和? extends Object是一样的。

        ? extends T称为受限通配(bounded wildcard),表示T或者T的一个子类型。

        ? super T称为下限通配(lower-bounded wildcard),表示T或者T的一个父类型。

        通配符,打印栈中的对象以及清空栈。<?>是一个通配符,表示任何一种对象类型。它等价于<? extends Object>。

5、消除泛型对泛型的限制

        编译器可以使用泛型信息,但这些信息在运行时是不可用的。这被称为类型消除。

  泛型是使用一种叫做类型消除(擦除)的方法来实现的。编译器使用泛型类型信息来编译代码,但是随后会消除它。因此,泛型信息在运行时是不可用的。这种方法可以使泛型代码向后兼容使用原始类型的遗留代码。

  泛型存在于编译时。一旦编译器确认泛型类型是安全使用的,就会将它转换为原始类型。例如:编译器检查左边的代码里泛型是否被正确使用,然后将它翻译成右边的代码。

 由于泛型类型在运行时被擦除,因此,对于如何使用泛型类型是有一些限制的。见(6、对泛型的限制)。

6、对泛型的限制

  限制1:不能使用new T()

    运行时泛型T是不可用的。

   限制2:不能使用new T[]

    可以通过创建一个Object的数组,然后将它的类型转换为T[]来规避这个限制,

    E[] elements = (E[])new Object[capacity];

    类型转换到E[]会导致一个免检的编译警告,因为编译器无法确保在运行时类型转换是否能成功,这种类型的编译警告是使用java泛型的不足之处,也是无法避免的。

  使用泛型类型创建泛型数组也是不允许的。

    GenericStack<String>[] stack = new GenericStack<String>[10];//错误的

  可以修改为下面代码来规避,但是会有编译警告

    GenericStack<String>[] stack = (GenericStack<String>[])new GenericStack [10];

  限制3:在静态上下文中不允许类的参数是泛型类型

  由于泛型类的所有实例都有相同的运行时类,所以泛型类的静态变量和方法是被它的所有实例所共享的。因此,在静态方法、数据域或者初始化的语句中,为类引用泛型类型参数是非法的。

  限制4:异常类不能是泛型的

7、泛型矩阵类

        对于所有矩阵,除了元素类型不同以外,它们的加法和乘法操作都是类似的。因此,可以设计一个父类,不管它们的元素类型是什么,该父类描述所有类型的矩阵共享的通用操作,还可以创建若干个适用于指定矩阵类型的子类。

import com.iweb.generic.exception.MatrixException;

/**
 * 使用泛型来设计用于矩阵运算的类
 * @param <T>
 */
public abstract class GenericMatrix<T extends Number> {
    protected  abstract T add(T num1, T num2);
    protected  abstract T multiply(T num1, T num2);
    protected  abstract T zero();
    
    /**
     * 矩阵加法
     */
    public T[][] addMatrix(T[][] matrix1,T[][] matrix2){
        if(matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length)
            throw new MatrixException("两个矩阵的行列不相等,不能完成加法操作");
        @SuppressWarnings("unchecked")
        T[][] results = (T[][])new Number[matrix1.length][matrix1[0].length];
        for(int i = 0; i < results.length;i++) {
            for(int j = 0; j < results[i].length;j++) {
                results[i][j] = add(matrix1[i][j], matrix2[i][j]);
            }
        }
        return results;
    }
    
    /**
     * 将泛型类型T[][]的两个矩阵进行相乘
     */
    public T[][] multiplyMatrix(T[][] matrix1,T[][] matrix2){
        if(matrix1[0].length != matrix2.length) {
            throw new MatrixException("两个矩阵不符合乘法运算规则");
        }
        @SuppressWarnings("unchecked")
        T[][] results = (T[][])new Number[matrix1.length][matrix2[0].length];
        for(int i = 0; i < results.length; i++) {
            for(int j = 0; j < results[0].length;j++) {
                results[i][j] = zero();
                for(int k = 0; k < matrix1[0].length;k++) {
                    results[i][j] = add(results[i][j],multiply( matrix1[i][k], matrix2[k][j]));
                }
            }
        }
        return results;
    }
    //显示矩阵、操作以及它们的结果
    public static void printResult(Number[][] matrix1,Number[][] matrix2,Number[][] matrix3,char operator) {
        for(int i = 0; i < matrix1.length; i++) {
            for(int j = 0; j < matrix1[0].length; j++)
                System.out.print(" " + matrix1[i][j]);
            if(i == matrix1.length / 2)
                System.out.print("  " + operator + "  ");
            else
                System.out.print("      ");
            for(int j = 0;j < matrix2[0].length; j++) {
                System.out.print(" " + matrix2[i][j]);
            }
            if(i == matrix1.length / 2)
                System.out.print("  =  ");
            else
                System.out.print("     ");
            for(int j = 0;j < matrix3[0].length; j++) 
                System.out.print(matrix3[i][j] + " ");
            System.out.println();
        }
        System.out.println();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值