jdk——泛型介绍

本文深入探讨了Java中的泛型,包括泛型类、接口和方法的创建,以及泛型通配符的使用。通过实例展示了泛型如何确保类型安全、避免强制转换并提高代码重用性。同时,解释了泛型的类型擦除现象和可能的堆污染问题,以及桥接方法的概念。
摘要由CSDN通过智能技术生成

本质是参数化类型

可以用在类,接口,方法的创建中

  • 类——泛型类.note

public class GenericCla<T,P> {
    public T method1(T t){
        return t;
    }

    public P method2(P p){
        return p;
    }

    public <P> P method3(){
        return null;
    }
}
  • 接口——泛型接口.note

// 定义接口
public interface CalGenneric <T>{
    T add(T a,T b);
    T sub(T a,T b);
    T mul(T a,T b);
    T div(T a,T b);
}

// 实现接口
public class DoubleCalc<Double> implements CalGenneric<Double>{
    @Override
    public Double add(Double a, Double b) {
        return null;
    }

    @Override
    public Double sub(Double a, Double b) {
        return null;
    }

    @Override
    public Double mul(Double a, Double b) {
        return null;
    }

    @Override
    public Double div(Double a, Double b) {
        return null;
    }
}
  • 方法——泛型方法.note

public class GenericMethod<K,V> {
    /**
     * 1、实体方法使用类上定义的泛型
     * @param k
     * @param v
     * @return
     */
    public K method1(K k,V v){
        return null;
    }

    public <T> T method02(){ //2、方法上定义泛型
        return null;
    }


    /**
     * 静态方法中不能直接使用类上定义的泛型
     * 静态方法中可以使用方法上定义的泛型
     * @return
     */
//    public static V method03(){
//        return null;
//    }

    /**
     * class new的时候才加载,所以静态方法中不能直接使用类上定义的泛型   
     * static 声明优先于类加载,所有需要先声明
     */
    public static <P> P method04(){
        return null;
    }
}

先声明,再使用

泛型通配符

无界通配符 ?

上界通配符 ? extends Number

下界通配符 ? supper Inteher

import java.util.ArrayList;

/**
 * 泛型通配符:边界的问题
 * 三种边界
 * 无界:?<?>
 * 上界: <? extends E>
 * 下界: <? super E>
 *
 *  编译检查 保证类型的安全
 *  避免强制转换的硬编码
 *  增加调用代码的重用性
 */
public class BoderDemo {

    /**
     * 无界通配符的使用
     */
    public void border01(ArrayList<?> arrayList){
        for (int i=0;i<arrayList.size();i++){
            System.out.println(arrayList.get(0));
        }
    }

    /**
     * 上界通配符的使用
     * <? extends Object> 无界通配符
     */
    public void border02(ArrayList<? extends Number> arrayList){
        for (int i=0;i<arrayList.size();i++){
            System.out.println(arrayList.get(0));
        }
    }

    /**
     * 下界通配符的使用
     */
    public void border03(ArrayList<? super Number> arrayList){
        for (int i=0;i<arrayList.size();i++){
            System.out.println(arrayList.get(0));
        }
    }

    public static void main(String[] args) {
        BoderDemo boderDemo = new BoderDemo();
        ArrayList<String> strList = new ArrayList<>();
        ArrayList<Object> objList = new ArrayList<>();
        ArrayList<Number> numberArrayList = new ArrayList<>();
        ArrayList<Double> doubleArrayList = new ArrayList<>();
        ArrayList<Integer> intArrayList = new ArrayList<>();

        //无界
        boderDemo.border01(strList);
        boderDemo.border01(numberArrayList);
        boderDemo.border01(intArrayList);

        //上界
        boderDemo.border02(numberArrayList);
        boderDemo.border02(doubleArrayList);
//        boderDemo.border02(strList); //泛型编译检查
        //下界
        boderDemo.border03(objList);
    }
}

作用 

编译检查 保证类型的安全

避免强制转换的硬编码

增加调用代码的重用性

编译检查

  • 没有进行泛型约束的类
import java.io.File;

public class ArryListNoGeneric {
    private Object[] elements= new Object[4];
    private int size;

    public Object get(int i){
        if (size>i) return elements[i];
        throw new IndexOutOfBoundsException();
    }

    public void add(Object c){
        elements[size++]=c;
    }

    public static void main(String[] args) {
        ArryListNoGeneric list = new ArryListNoGeneric();
        list.add(1);
        list.add("a");
        list.add(new File("d:/nxjy"));
        System.out.println(list.size);
        String str =  (String) list.get(2);

    }
}
  • 有泛型约束的类

import java.io.File;

public class ArryListHasGeneric<E> {
    private Object[] elements= new Object[4];
    private int size;

    public Object get(int i){
        if (size>i) return elements[i];
        throw new IndexOutOfBoundsException();
    }

    public void add(E c){
        elements[size++]=c;
    }

    public static void main(String[] args) {
        ArryListHasGeneric<String> list = new ArryListHasGeneric<String>();
//        list.add(1);  // 类型检查
        list.add("a");
//        list.add(new File("d:/nxjy"));   // 类型检查
        System.out.println(list.size);
        String str =  (String) list.get(2);
    }
}

避免强制转型类型

import java.util.ArrayList;
import java.util.List;

/**
 * 1、保证类型安全,编译阶段类型检查
 * 2、避免类型转换硬编码
 * 3、调用代码重用性
 */
public class ArryListDemo {

    public void hasGen(){
        List<Integer> list = new ArrayList<>(); //1.7
        list.add(123);
        list.add(124);
        System.out.println("---------------");
        System.out.println(list.get(0).compareTo(list.get(1)));


    }

    public void noGen(){
        List list = new ArrayList();
        list.add(123);
        list.add(124);
        System.out.println("---------------");
        System.out.println(((Integer) list.get(0)).compareTo((Integer)list.get(1)));

    }
}

增加调用代码的重用性

import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class Reuse<T extends Comparable>{

    public Integer compaerTo(T t1,T t2){
        return t1.compareTo(t2);
    }

    @Test
    public void testComara(){
        Reuse<Integer> reuse = new Reuse<>();
        System.out.println(reuse.compaerTo(123,234)==0);
        /**
         * 相当于一个三目运算符,如果结果为false,打印提示语
         */
        assertTrue("正常对比",reuse.compaerTo(123,234)==0);

        Reuse<String> stringReuse = new Reuse<>();
        Integer integer = stringReuse.compaerTo("!23", "234");
        System.out.println(integer);
    }
}

泛型的类型擦除

泛型只在编译阶段有效,泛型类型在逻辑上可看成是多个不同的类型,但是其实质都是同一个数据类型(Object)。

编译之后编译器会才去泛型化的措施。

  1. java中的泛型是假泛型
  2. 编译之后没有泛型 
  3. import org.junit.Test;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    
    
    /**
     * 泛型并不影响数据的基本类型
     * 伪泛型,Java编译期间会将泛型擦除
     */
    public class GenType {
    
        @Test
        public void m01(){
            List list = new ArrayList();
            List<String> strList = new ArrayList<String>();
    
            System.out.println(list.getClass());
            System.out.println(strList.getClass());
            System.out.println(list.getClass()==strList.getClass()); //true?false?
        }
    
        @Test
        public void method02() throws Exception {
            List<String> list = new ArrayList<>();
            list.add("a");
            list.add("b");
    //        list.add(1);  //约束类型
            System.out.println(list.size());
            System.out.println("-------------------------");
    
            /**
             * 泛型擦除
             * 改变定于的泛型,诠释java的泛型是伪泛型,编译之后class会进行泛型的擦除
             * 通俗来讲,就是泛型只在编译阶段起作用,生成class文件之后就不起作用
             */
            Class<? extends List> clazz = list.getClass();
            Method m = clazz.getDeclaredMethod("add", Object.class);
            m.invoke(list,new Object());
            System.out.println(list.size());
        }
    }

堆污染

当一个可变泛型参数指向一个无泛型参数时,堆污染就有可能发生

  • 案例1

    import java.util.Set;
    import java.util.TreeSet;
    /**
     * 当一个可变泛型参数执行一个无泛型参数时,堆污染
     */
    public class Pollution {
    
        public static void main(String[] args) {
            Set set = new TreeSet();
            set.add("addd");
            set.add(100);
            System.out.println(set.size());
        }
    }
  • 案例2
    import java.util.Set;
    import java.util.TreeSet;
    /**
     * 当一个可变泛型参数执行一个无泛型参数时,堆污染
     */
    public class Pollution {
    
        public static void main(String[] args) {
             Set<Object> set = new TreeSet();
            set.add("addd");
            set.add(100);
            System.out.println(set.size());
        }
    }
  • 案例3
    import java.util.Set;
    import java.util.TreeSet;
    
    /**
     * 当一个可变泛型参数执行一个无泛型参数时,堆污染
     */
    public class Pollution {
    
        public static void main(String[] args) {
            Set set = new TreeSet();
            set.add("addd");
            varagMethod(set);
        }
    
        private static void varagMethod(Set<Integer> set) {
            System.out.println(set.size());
        }
    }
  • 案例4
    import java.util.Set;
    import java.util.TreeSet;
    
    /**
     * 当一个可变泛型参数执行一个无泛型参数时,堆污染
     */
    public class Pollution {
    
        public static void main(String[] args) {
            Set set = new TreeSet();
            varagMethod(set);
        }
    
        private static void varagMethod(Set<Integer> set) {
            set.add(new Integer(100));
            System.out.println(set.size());
        }
    }
  • 案例5
    import java.util.Set;
    import java.util.TreeSet;
    
    /**
     * 当一个可变泛型参数执行一个无泛型参数时,堆污染
     */
    public class Pollution {
    
        public static void main(String[] args) {
            Set set = new TreeSet();
            set.add("addd");
            varagMethod(set);
        }
    
        private static void varagMethod(Set<Integer> set) {
            System.out.println(set.size());
        }
    }
  • 案例6
    import java.util.Set;
    import java.util.TreeSet;
    
    /**
     * 当一个可变泛型参数执行一个无泛型参数时,堆污染
     */
    public class Pollution {
    
        public static void main(String[] args) {
            Set set = new TreeSet();
            set.add("addd");
            varagMethod(set);
        }
    
        private static void varagMethod(Set<Integer> set) {
            set.add(new Integer(100));
            System.out.println(set.size());
        }
    }

桥接

1.5之后引入泛型后,为了使java的放心方法生成的字节码和1.5之前的字节码相兼容,编译器自动生成的方法叫做桥接

泛型接口

public interface SuperClass<T> {
    T m01(T param);
}

类实现泛型接口

public class SubClass implements SuperClass<String>{
    @Override
    public String m01(String param) {
        return param + "---";
    }
}

测试

public class BridgeMethosTest {
    public static void main(String[] args) {
        SuperClass superClass = new SubClass();
        System.out.println(superClass.m01("qwer"));
        System.out.println(superClass.m01(new Object()));
    }
}

javap命令看桥接的实现

javap -p -v SubClass.class

jdk1.5之后自动桥接适配,多加了一个类型为Object的m01方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值