在java中我们定义接口其实定义的是这个类的功能,在很多时候我们并不关心这个类的类型而是这个类的能力。泛型的出现让我们的代码和代码所能操作的类型不在绑定在一起,不仅可以复用代码降低耦合还可以提高代码的可读性和安全性。
首先,我们现在看一段代码来介绍一下泛型的基本概念:
public class Generic{ T one; T two; public Generic(T one, T two){ this.one = one; this.two = two; } public T getOne() { return one; } public T getTwo() { return two; }}
其中Generic就是一个泛型类,T叫做类型参数。泛型就是把类型参数化,这样代码能够处理的类型可以通过参数的形式传递。在调用时可以通过:
Genericgeneric = new Generic (1,100); Integer one = generic.getOne(); Integer two = generic.getTwo();
其中Integer就是传递的实际类型的参数,这样就实现了Generic类的代码和它能处理的类型的解耦。在Generic中的类型参数可以有多个,例如:
public class Generic{ K one; V two; public Generic(K one, V two){ this.one = one; this.two = two; } public K getOne() { return one; } public V getTwo() { return two; } public static void main(String[] args) { Generic generic = new Generic (1,"hello world"); Integer one = generic.getOne(); String two = generic.getTwo(); }}
当需要多个类型参数时用“,”隔开。
知道了如何定义泛型下面我们来介绍一下泛型的基本原理。在介绍泛型的基本原理之前我们需要先介绍一点java的基础知识。在java中有java编译器和java虚拟机其中java编译器的工作就是把我们编写的.java文件编译成java虚拟机可以识别的字节码文件。对于泛型类,java编译器会把泛型代码编译成非泛型代码,也就是说在java编译器会将类型参数擦除然后替换为Object类型然后加入必要的强制类型的转换。java虚拟机在执行的时候是完全不知道泛型的存在只知道普通的类代码和实现。
了解了泛型的基本使用方法和基本原理,可能我们会有疑问:既然如此为什么不一开始只使用普通类和Object类而要使用泛型呢?使用泛型有两个好处:1、提高代码的可读性。2、更好的安全性。如果不使用泛型而使用Object类型则需要在代码中进行强制类型转换,这样的话就会有一个问题就是有些强制类型转换在代码的编译期不会报错,但是会在代码的运行期间报错。使用了泛型可以很好的规避这种情况的发生,代码在编译期间就会报错提高了代码的安全性。
在java中除了类可以是泛型的方法也可以是泛型的。这里需要注意,在java类中泛型方法和其所在类是否是泛型无关。下面我们来先定义一个泛型方法:
public staticboolean contains(T[] arrays,T param){ boolean flag = false; for (T t : arrays) { if(t.equals(param)){ flag= true; break; } } return flag; }
这个方法就是一个泛型方法,其中泛型参数为T放在返回值的前面。同样的泛型方法也可以有多个泛型参数,使用“,”隔开即可。