JVM[day13]

编译期处理

语法糖:就是指java编译器把 .java源码编译为 .class字节码的过程中,自动生成和转化一些代码,主要是为了减轻程序员的负担

默认构造器

如以下代码:

public class Candy1{
}

编译后成class的代码:

public class Candy1{
	public Cany1(){
		super();
	}
}

可以看到编译后的class代码中调用了无参构造方法,这个就是编译器给我们加上的

自动拆装箱

指java的基本类型和包装类型的转换,这个特性是jdk5开始加入的

public class Demo_17 {
    public static void main(String[] args) {
        Integer x=1;
        int y=x;
    }
}

这段代码在jdk5之前是无法编译通过的,必须改为一下样式:

 public static void jdk5(){
        Integer x=Integer.valueOf(1);
        int y=x.intValue();
    }

泛型集合取值

泛型也是在jdk5开始加入的特性,但java在编译泛型代码后会执行泛型擦除动作,即泛型信息在编译为字节码后就丢失了,实际的类型都当做了Object类型来处理

public class Demo_18 {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList<>();
        list.add(10);//实际调用的是list.add(Object e)
        Integer x=list.get(0);//实际调用的是Object obj=list.get(int index)
    }
}

通过反编译以及注解可以看出来:
在这里插入图片描述
擦除的是字节码上的泛型信息,还有一部分泛型信息会被保留下来,通过反编译可以看到:
在这里插入图片描述
可以看到泛型信息,但是有一些局限性,局部变量的泛型信息,虽然没有被擦除,但是我们没法用反射的方式拿到这些信息,只有在方法的参数和返回值上带有泛型信息,才可以通过反射的方式得到,如以下代码:

public class Demo_19 {
    public static void main(String[] args) throws Exception {
        Method test=Candy3.class.getMethod("test",List.class,Map.class);//得到方法对象
        Type[] types = test.getGenericParameterTypes();//得到泛型参数的类型信息
        for (Type type:types) {//遍历types数组
            if(type instanceof ParameterizedType){//判断type是不是一个泛型
                ParameterizedType parameterizedType= (ParameterizedType) type;//如果是,进行转化
                System.out.println("原始类型-"+parameterizedType.getRawType());//getRawType()得到原始信息
                Type[] arguments = parameterizedType.getActualTypeArguments();//得到泛型的参数
                for (int i = 0; i < arguments.length; i++) {//遍历参数
                    System.out.printf("泛型参数与[%d] - %s\n",i,arguments[i]);
                }
            }
        }
    }
}
class Candy3{
    public void test(List<String> list, Map<Integer,Object> map){

    }
}

代码运行截图如下:
在这里插入图片描述

可变参数

可变参数也是jdk5开始加入的新特性:
例如:

public class Demo_20 {
    public static void foo(String...args){
        String[] arr=args;
        System.out.println(arr);
    }
    public static void main(String[] args) {
        foo("hello","world","aaaa");
    }
}

可变参数String...args其实是一个Sting[] args,从代码中的复制语句中就可以看出来,同样的java编译器会在编译期间将上述代码转换为:

public class Demo_20 {
    public static void foo(String[] args){
        String[] arr=args;
        System.out.println(arr);
    }
    public static void main(String[] args) {
        foo("hello","world","aaaa");
    }
}

注意
如果调用了foo()则等价代码为foo(new String()),创建了一个空的数组,而不会传递null进去

foreach循环

还是jdk5引入的语法糖,数组的循环:

public class Candy5 {
    public static void main(String[] args) {
        int[] array={1,2,3,4,5};
        for (int i:array) {
            System.out.println(i);
        }
    }
}

会被编译器转化为:

 int[] arr=new int[]{1,2,3,4,5};
        for (int i = 0; i < array.length; i++) {
            int e=array[i];
            System.out.println(e);
        }

而集合的循环:

 List<Integer> list= Arrays.asList(1,2,3,4,5);
        for (Integer i:list) {
            System.out.println(i);
        }

实际会被编译器转换为迭代器的调用

Iterator iterator = list.iterator();//迭代器
        while (iterator.hasNext()){//判断有没有下一个元素
            Integer e= (Integer) iterator.next();//获取下一个元素
            System.out.println(e);
        }

注意:
foreach循环写法,能够配合数组,以及所有实现了Iterable接口的集合类一起使用,其中Iterable用来获取集合的迭代器(Iterator)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值