指的是在类定义的时候并不会设置类中的属性或方法中的具体类型,而是在类使用时再进行定义。
泛型是JAVA中的语法糖。(语法糖:方便开发者开发,在运行阶段无用)
1.类型不一致会在编译期报错,确保在创建对象,存放对象或调用方法时使用的是正确的类型。
2.杜绝了向下转型带来的安全隐患,避免在运行时出现ClassCastException
示例:
public class Myclass {
T value1;
T value2;
public Myclass(T value1,T value2){
this.value1=value1;
this.value2=value2;
}
public void Print() {
System.out.println("value1:"+value1);
System.out.println("value2:"+value2);
}
创建对象:
Myclass m1=new Myclass("Hello","bit");
m1.Print();//调用方法
当然泛型也可以指定为任何引用类型,甚至是自己定义的类型:
public class Myclass {
T value1;
T value2;
public Myclass(T value1,T value2){
this.value1=value1;
this.value2=value2;
}
public void Print() {
System.out.println("value1:"+value1);
System.out.println("value2:"+value2);
}
public static void main(String[] args) {
Myclass m1=new Myclass("Hello","bit");
m1.Print();
Myclass m2=new Myclass(10,12);
m2.Print();
Myclass m3=new Myclass(20.2,13.0);
m3.Print();
Myclass m4=new Myclass(new Class1("bit"),new Class1("bit"));//自己定义的类型
m4.Print();
}
}
class Class1 {
String value;
public Class1(String Name) {
this.value=Name;
}
@Override
public String toString() {
return this.value;
}
}
在JDK1.7之后:创建对象是后面的一个泛型参数可以不写,即:
Myclass m1=new Myclass<>("Hello","bit");
泛型接口:
使用方法与泛型接口基本相同,但是在在子类实现接口的时候有两种方法
1.子类实现仍然使用泛型。
interface IF{
void Print();
}
public class Myclass implements IF { //Myclass仍然使用泛型,子类的使用与泛型类使用一致
T value1;
T value2;
public Myclass(T value1,T value2){
this.value1=value1;
this.value2=value2;
}
public void Print() {
System.out.println("value1:"+value1);
System.out.println("value2:"+value2);
}
2.子类指定具体类型,则后面子类只能使用指定的类型
interface IF{
void Print();
}
public class Myclass implements IF {
String value1;
String value2;
public Myclass(String value1,String value2){
this.value1=value1;
this.value2=value2;
}
public void Print() {
System.out.println("value1:"+value1);
System.out.println("value2:"+value2);
}
public static void main(String[] args) {
Myclass m1=new Myclass("Hello","bit");
m1.Print();
泛型方法:
示例:
public T Method(T t) {
return t;
}
使用时直接调用即可,如:
new Mylass().Method("bit");
在一个类中可以同时使用了泛型类和泛型方法:
public class Myclass{
V value1;
V value2;
public Myclass(V value1,V value2){
this.value1=value1;
this.value2=value2;
}
public T Method(T t) {
return t;
}
public void Print() {
System.out.println("value1:"+value1);
System.out.println("value2:"+value2);
}
public static void main(String[] args) {
Myclass m1=new Myclass("Hello","bit");
m1.Print();
m1.Method(20);
}
}
在上一个例子中,V和K表示的不是同一种类型,所以V在创建对象时被指定为了String类型,但是Method方法同样可以使用其他类型。同时不建议泛型类和泛型方法的泛型使用同一个字母。
在通配符:
可以接受所有的泛型参数但是不能让用户随意修改。
public class Myclass{
V value1;
public Myclass(V value1){
this.value1=value1;
}
public V getValue1() {
return value1;
}
public void setValue1(V value1) {
this.value1 = value1;
}
public static void Print(Myclass> m) {
System.out.println("value1:"+m.value1);
// m.setValue1(15); 通配符取得的值不可以修改,只可以访问
}
public static void main(String[] args) {
Myclass m1=new Myclass("Hello");
Print(m1);
Print(new Myclass(10));
}
}
设置类型上限,可以用于类或方法,所指定的类型只能是T及T的子类。在方法中还是不可以修改其值。
public class Myclass{
V value1;
public Myclass(V value1){
this.value1=value1;
}
public V getValue1() {
return value1;
}
public void setValue1(V value1) {
this.value1 = value1;
}
public static void main(String[] args) {
Myclass m1=new Myclass<>(11);
Myclass m3=new Myclass(20.2);
}
}
public void Print(T A) {
System.out.println("value1:"+A);
}
设置类型下限,只可用于方法,可以修改其值。
public static void Print(Myclass super Integer> m ) {
System.out.println("value1:"+m.value1);
}
//调用:
Myclass m1=new Myclass<>(11);
Print(m1);
泛型是通过类型擦除来实现的,编译器在编译时(进入JVM之前)擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息这样做的目的,是确保能和Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。
public class Myclass{
V value1;
public Myclass(V value1){
this.value1=value1;
}
public V getValue1() {
return value1;
}
public void setValue1(V value1) {
this.value1 = value1;
}
public void Print() {
System.out.println("value1:"+value1);
}
public static void main(String[] args) {
Myclass m1=new Myclass<>(11);
Myclass m2=new Myclass(20.2);
System.out.println(m1.getClass()==m2.getClass()); //打印结果为true
}
}