【Java核心技术卷】Java常见的12个语法糖

转自 https://blog.csdn.net/coder_what/article/details/96310967
附 Java中常用的反编译工具

文章目录

  • switch
  • forEach
  • lambda
  • if
  • enum
  • tryWithResource
  • assert
  • 变长参数
  • 自动装拆箱
  • 泛型
  • 内部类
  • 多态

switch

public class tesst{
    public static void main(String[] args) {
        String string = "world";
        switch (string){
            case "hello":
                System.out.println(string);
                break;
            case "world":
                System.out.println(string);
                break;
            default:
                break;
        }
    }
}

编译后的代码

public class tesst {
    public static void main(String[] args) {
        String string;
        String string2 = string = "world";
        int n = -1;
        switch (string2.hashCode()) {
            case 99162322: {
                if (!string2.equals("hello")) break;
                n = 0;
                break;
            }
            case 113318802: {
                if (!string2.equals("world")) break;
                n = 1;
            }
        }
        switch (n) {
            case 0: {
                System.out.println(string);
                break;
            }
            case 1: {
                System.out.println(string);
                break;
            }
        }
    }
}

这样我们可以看出来,字符串需要先进行hash,然后为了防止hash碰撞,又加了equals

之前阿里妹在公众号上发了五道题,其中有一个是这样的:

public class SwitchTest {
    public static void main(String[] args) {
        String param = null;
        switch (param) {
            case "null":
                System.out.println("null");
                break;
            default:
                System.out.println("default");
        }
    }
}

这个题有三种选项,一种是输出null,一种是走default,最后一种是报错。

通过语法糖我们可以发现,switch中比较的是hashCode的值,而null.hashCode()自然会爆出空指针异常
``

forEach

原来的代码

public class ForEach {
    public static void main(String[] args) {
        String[] s = {"fxxk","suger","fxxk","java"};
        for (String s1 : s) {
            System.out.println(s1);
        }
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        for (Integer integer : list) {
            System.out.println(integer);
        }
    }
}

编译后的代码

public class ForEach{
    public ForEach(){
    }

    public static void main(String args[]){
        String s[] = {
            "fxxk", "suger", "fxxk", "java"
        };
        String args1[] = s;
        int j = args1.length;
        for(int k = 0; k < j; k++){
            String s1 = args1[k];
            System.out.println(s1);
        }

        List list = new ArrayList();
        for(int i = 0; i < 10; i++)
            list.add(Integer.valueOf(i));

        Integer integer;
        for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(integer))
            
            integer = (Integer)iterator.next();
    }
}

可见,通过集合类是通过迭代器来实现了增强for循环,String通过普通的for循环来增强for循环。同时,因为其用了迭代器,我们需要注意,在foreach的时候只能遍历,不能修改。否则会爆出java.util.ConcurrentModificationException异常

lambda

原始代码

import java.util.ArrayList;
import java.util.List;
public class Lambda {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        list.forEach(System.out::println);
    }
}

编译后代码

import java.io.PrintStream;
import java.lang.invoke.LambdaMetafactory;
import java.util.ArrayList;
import java.util.function.Consumer;

public class Lambda {
    public static void main(String[] arrstring) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        for (int i = 0; i < 10; ++i) {
            arrayList.add(i);
        }
        
        PrintStream printStream = System.out;
        printStream.getClass();
        
        arrayList.forEach(
            (Consumer<Integer>)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)V, println(java.lang.Object ), (Ljava/lang/Integer;)V)((PrintStream)printStream));
    }

}

我们可以看出lambda和内部类的不同之处,内部类是生成了多个类文件,而lambda则是在一个类文件中,最多生成多个方法而已

if

原始代码

    public static void main(String[] args) {
        if (true){
            System.out.println("true");
        }else{
            System.out.println("false");
        }
        if (false){
            System.out.println("false");
        }else{
            System.out.println(false);
        }
    }

编译过的文件

    public static void main(String args[])
    {
        System.out.println("true");
        System.out.println(false);
    }

enum

原始代码

public enum EnumClass {
    SPRING,SUMMER,FALL,WINTER;
}

编译后的代码

public final class EnumClass extends Enum
{

    public static EnumClass[] values()
    {
        return (EnumClass[])$VALUES.clone();
    }

    public static EnumClass valueOf(String name)
    {
        return (EnumClass)Enum.valueOf(suger/EnumClass, name);
    }

    private EnumClass(String s, int i)
    {
        super(s, i);
    }

    public static final EnumClass SPRING;
    public static final EnumClass SUMMER;
    public static final EnumClass FALL;
    public static final EnumClass WINTER;
    private static final EnumClass $VALUES[];

    static 
    {
        SPRING = new EnumClass("SPRING", 0);
        SUMMER = new EnumClass("SUMMER", 1);
        FALL = new EnumClass("FALL", 2);
        WINTER = new EnumClass("WINTER", 3);
        $VALUES = (new EnumClass[] {
            SPRING, SUMMER, FALL, WINTER
        });
    }
}

我们可以看出,枚举是继承了Enum类的,同时他也是final,即不可继承的。

tryWithResource

源代码

public class TryWith {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new                   FileReader("d:\\TryWith.jad"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

编译后的代码

public class TryWith
{
    public TryWith()
    {
    }
    public static void main(String args[])
    {
        try
        {
            BufferedReader br = new BufferedReader(new FileReader("d:TryWith.jad"));
            String line;
            try
            {
                while((line = br.readLine()) != null) 
                    System.out.println(line);
            }
            catch(Throwable throwable)
            {
                try
                {
                    br.close();
                }
                catch(Throwable throwable1)
                {
                    throwable.addSuppressed(throwable1);
                }
                throw throwable;
            }
            br.close();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
}

我们可以看到,是编译器帮我们把资源关闭了

assert

原始代码

public class Assert {
    public static void main(String[] args) {
        int a = 1;
        assert a > 0;
        System.out.println(a);
    }
}

编译代码

public class Assert
{

    public Assert()
    {
    }

    public static void main(String args[])
    {
        int a = 1;
        if(!$assertionsDisabled && a <= 0)
        {
            throw new AssertionError();
        } else
        {
            System.out.println(a);
            return;
        }
    }

    static final boolean $assertionsDisabled = !suger/Assert.desiredAssertionStatus();

}

我们可以看到,断言通过if语句来执行

变长参数

原始代码

public class Long {
    public static void main(String... args) {
        String[] zi = {"i","am","zi","10ng"};
        ma(zi);
    }

    private static void ma(String... args) {
        for (String arg : args) {
            System.out.println(arg);
        }
    }
}

编译之后

public class Long{
    public Long(){
    }

    public static transient void main(String args[]){
        String zi[] = {"i", "am", "zi", "10ng"};
        ma(zi);
    }

    private static transient void ma(String args[]){
        String as[] = args;
        int i = as.length;
        for(int j = 0; j < i; j++){
            String arg = as[j];
            System.out.println(arg);
        }
    }

自动装拆箱

原始代码

    public static void main(String[] args) {
        int a = 1;
        Integer b;
        b  = a;
        a = b;
    }

编译之后

    public static void main(String args[])
    {
        int a = 1;
        Integer b = Integer.valueOf(a);
        a = b.intValue();
    }

同时我们需要知道,在JDK5之后,Integer的操作中引入了一个新功能来节省内存和提高性能。即,整型对象通过使用相同的对象引用实现了缓存和重用。适用于整数值区间-128 至 +127。

泛型

源代码

public class Generic extends Pair<String>{
    private String first;
    @Override
    public void setFirst(String first) {
        this.first = first;
    }
}
class Pair<T>{
    private T first;
    private T second;

    Pair() {
    }
    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }
    public T getFirst() {
        return first;
    }
    public void setFirst(T first) {
        this.first = first;
    }
    public T getSecond() {
        return second;
    }
    public void setSecond(T second) {
        this.second = second;
    }
}

编译后的代码

public class Generic extends Pair{
    private String first;
	public Generic()    {
    }
    public void setFirst(String first)    {
        this.first = first;
    }
    public volatile void setFirst(Object obj)   {
        setFirst((String)obj);
    }
    public volatile void setSecond(Object obj)    {
        super.setSecond(obj);
    }
    public volatile Object getSecond()    {
        return super.getSecond();
    }
    public volatile Object getFirst()    {
        return super.getFirst();
    }
}
class Pair{
    Pair(){
    }
    public Pair(Object first, Object second)    {
        this.first = first;
        this.second = second;
    }
    public Object getFirst()    {
        return first;
    }
    public void setFirst(Object first)    {
        this.first = first;
    }
    public Object getSecond()    {
        return second;
    }
    public void setSecond(Object second)   {
        this.second = second;
    }
    private Object first;
    private Object second;
}

注意此处继承之后的桥接方法

同时,我们需要知道因为类型擦除而出现的错误

内部类

这个参考我的文章【Java核心技术卷】深入理解Java的内部类

多态

原始代码

class GrandFather{
    private int a;
    GrandFather() {
        a = 10;
    }
    public GrandFather method() {
        System.out.println("--------调用GrandFather method()方法");
        return new GrandFather();
    }
}
//父类
class Father extends GrandFather {
    private int b;
    Father() {
        b = 20;
    }
    @Override
    public Father method() {
        System.out.println("--------调用Father method()方法");
        return new Father();
    }
}

编译器编译过后的Father类:

class Father extends GrandFather
{
	private int b;
    Father(){
        b = 20;
    }
    public Father method(){
        System.out.println("--------\u8C03\u7528Father method()\u65B9\u6CD5");
        return new Father();
    }
    public volatile GrandFather method(){
        return method();
    }
}

你可能感兴趣的:(Java核心技术,Java)