Java中的泛型

概念:

java泛型是j2se 1.5引入的新特性,本质是参数化类型,将用到的数据类型指定为任意一种,可用在类、接口、方法中。可以用任意字母来表示,但一般使用大写字母T(Type的简写)来表示。

为什么要有泛型:

在j2se 1.5之前,java允许我们构建一个元素类型为Object的集合,我们可以对类型Object的引用来实现参数的“任意化”,这时编译是没有问题的,
但是在运行期间会出现问题,这是一个安全隐患,为了解决此问题,java 1.5 引入了泛型。

当我们不使用泛型的时候:

public class TestArrayList {
	 public static void main(String[] args) {
		
        ArrayList list1 = new ArrayList();//没有声明泛型的集合  
        list1.add("abc");//添加String类型
        list1.add(123);//添加Integer类型,编译阶段不会报错

        String str1 = (String) list1.get(0);
        String str2 = (String) list1.get(1);//运行期间会报错
	}
}

上面的例子表示在不声明泛型的时候,这个集合里面可以放任意类型的数据,并且在编译期间不显示错误,却出现了安全隐患。一个集合里面放多种类型的数据,没有做到解耦和单一职责,这样也是不推荐的。

当我们使用泛型的时候:

public class TestArrayList {
    public static void main(String[] args) {

        ArrayList <String>list1 = new ArrayList<String>();
        list1.add("abc");
        list1.add(123);//在编译阶段就会提示错误,避免隐患。
	}
}

泛型的使用

一、泛型类的使用

当我们不知道未来属性类型的时候,这种情况可以使用类型占位符进行占位

单个泛型的使用

下面声明一个泛型类

public class Person<T> {
    private T name;
    private T address;

    public T getAddress() {
        return address;
    }

    public void setAddress(T address) {
        this.address = address;
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }
}

我们在使用的时候,设定好属性的类型之后,就只能传入指定的泛型类型。

public class TestArrayList {
    public static void main(String[] args) {
        
        Person<String> person = new Person<String>();
        person.setName(123);//编译期间会报错;提示类型不匹配
        person.setAddress("China");
  	}
}

多个泛型的使用

上面的Person类中声明了两个属性,但是如果我想让这两个属性的类型是不一样的怎么办?这个时候可以声明多个泛型。
声明一个泛型类:

public class Animal<K,V> {

    private K name;
    private V age;

    public K getName() {
        return name;
    }

    public void setName(K name) {
        this.name = name;
    }

    public V getAge() {
        return age;
    }

    public void setAge(V age) {
        this.age = age;
    }
}

我们在调用的时候,只能按照泛型类型声明的顺序给属性赋值。
下面String 和Integer的声明顺序分别对应泛型类中name 和age的声明顺序。

public class TestArrayList {
    public static void main(String[] args) {
        
        Animal<String, Integer> animal = new Animal<String, Integer>();
        animal.setName("Tom");
        animal.setAge(18);
    }
}
       

二、泛型方法的声明

普通的泛型方法

泛型类以及方法的声明:

public class Person1<T,K> {
    public void showName(T name) {
        System.out.println(name);
    }

    public void showAge(K age){
        System.out.println(age);
    }
}

方法的调用:

public class TestArrayList {
    public static void main(String[] args) {
        
        Person1<String,Integer> person1 = new Person1<String,Integer>();
        person1.showName("Jack");
        person1.showAge(19);
	}
}

静态的泛型方法

静态泛型方法中的类型占位符和类中的占位符是没有关系的。
这是因为不用static修饰的方法和所在的类不是同一级别,运行时只会加载类,不会加载非static修饰的方法和变量;而用static修饰的方法是和类同一级别的,都是在类加载的时候进行初始化,所以类上面的泛型类型无法应用于static修饰的方法里面。它俩各论各的。

public class Person1<T,K> {
    public void showName(T name) {
        System.out.println(name);
    }

    public void showAge(K age){
        System.out.println(age);
    }
    //静态方法中的泛型和类中的泛型没有关系,所以此行代码会报错
    public static void show2( T t){
        System.out.println(t);
    }

在这里插入图片描述
如果想要在static修饰的方法里面使用泛型,应该使用如下写法:
在static后面先声明泛型,然后在参数中声明泛型变量。

在这里插入图片描述
调用方法:

public class TestArrayList {
    public static void main(String[] args) {
        Person1.show2("Jerry");
    }
 }

另外,如果想让方法只依赖于自己的泛型,直接在方法的public后面声明即可。

public class Person1<T,K> {
	public <S> void show3(S name) {
        System.out.println(name);
    }
}

调用:

public class TestArrayList {
    public static void main(String[] args) {

        Person1<String,Integer> person1 = new Person1<String,Integer>();
        person1.show3(111);
     }
 }

三、泛型接口

首先在接口中声明泛型

public interface IPlant<T> {
    public void eat(T t);
}

实现类A实现该接口

public class Flower implements IPlant<Integer> {
    public void eat(Integer integer) {
  
    }
}

实现类B实现该接口

public class Tree implements IPlant<String >{
    public void eat(String string ) {

    }
}

由此可见,不同类型的实现类可以实现相同的接口,但是如果泛型接口的实现类没有指定具体的泛型类型,必须要在这个实现类中声明一个泛型类型占位符。如下:

public class Flower<T> implements IPlant<T> {
    public void eat(T integer) {
    
    }
}

四、泛型擦除模式

java中的泛型只存在于代码编译阶段,在运行期间泛型类型是会被去除掉的,这个就叫做擦除模式。
如下代码输出的结果显示为true
在这里插入图片描述
如上两个集合的类型不同,但是比较他们的class,返回的却是true,说明在运行阶段,java消除了泛型的类型。
其实在运行阶段它默认的形式如下:

Person p1= new Person();
Person p2= new Person();

泛型擦除的原因有两种说法:
1、为了兼容jdk老版本的编码,之前jdk有一个list,现在也有一个,如果不擦除会有冲突。
2、为了防止创建泛型时造成过度资源消耗。

<think>好的,我现在需要帮助用户了解Java的使用方法和示例。首先,用户提供的引用内容提到类、方法、静态方法的以及伪的概念。我需要结合这些信息,整理出一个结构清晰的回答,并确保遵循系统级指令中的格式要求。 首先,用户可能对的基本概念不太清楚,所以需要先简单解释什么是,以及它的作用,比如类安全、代码复用等。然后,分点介绍的不同用法,比如类、方法、接口,每个部分都要有示例代码,并且代码中的数学表达式要用$...$格式,比如在解释方法时,如果有涉及类参数T,可以用$T$来表示。 接下来,需要注意引用内容中提到的伪,说明Java在编译时类擦除的特性,这可能会影响运行时无法获取的具体类。此外,用户可能想知道如何使用通配符和边界,比如上界和下界通配符,这部分需要给出示例,并正确应用LaTeX格式,比如$? extends Number$。 用户还提到静态方法的,需要特别注意静态方法不能使用类定义的,而必须自己声明,这点要强调,避免常见错误。示例代码需要正确展示如何在静态方法中定义类参数。 最后,生成相关问题时要考虑用户可能进一步想知道的内容,比如类擦除的影响、通配符的使用场景、与集合框架的结合,以及类边界的作用。确保每个问题都有针对性,帮助用户深入理解。 现在检查是否有遗漏,比如是否覆盖了所有引用中的要点,引用的标识是否正确添加,示例代码是否符合语法,数学表达式是否正确使用$符号。同时,确保回答结构清晰,分点明确,符合用户可见层的要求。</think>### Java使用方法及示例 Java用于实现**类参数化**,提高代码复用性和类安全性[^1]。以下是具体用法及示例: --- #### 一、类 定义类时声明类参数$T$,可在类中作为类使用: ```java public class Box<T> { private T content; public void setContent(T content) { this.content = content; } public T getContent() { return content; } } // 使用示例 Box<String> stringBox = new Box<>(); stringBox.setContent("Hello"); ``` --- #### 二、方法 在方法返回值前声明类参数$T$,可在非类中使用: ```java public class Utils { public static <T> T getMiddle(T[] arr) { return arr[arr.length/2]; } } // 调用示例 String[] names = {"Alice", "Bob", "Charlie"}; String middle = Utils.<String>getMiddle(names); // 返回"Bob" ``` --- #### 三、接口 定义接口时声明类参数,常用于集合类: ```java public interface List<T> { void add(T element); T get(int index); } // 实现示例 class StringList implements List<String> { // 必须使用String类实现方法 } ``` --- #### 四、类边界 限制范围: ```java public static <T extends Number> double sum(T a, T b) { return a.doubleValue() + b.doubleValue(); } // 只能传入Number及其子类 sum(10, 20.5); // 合法 sum("a", "b"); // 编译错误 ``` --- #### 五、通配符 处理未知类集合时使用: ```java // 上界通配符 void process(List<? extends Number> list) { /* 可读不可写 */ } // 下界通配符 void addNumbers(List<? super Integer> list) { /* 可写不可读 */ } ``` --- #### 关键特性 1. **类擦除**:编译后会被替换为Object或边界类[^3] 2. **静态方法限制**:静态方法需单独声明: ```java public static <T> void print(T item) { System.out.println(item); } ``` ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值