一定一定要向前看
之前在学习Java基础的时候,零零碎碎地看了一些语法糖相关,今天记录下来
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 }); } } public static final Enum SPRING; public static final Enum SUMMER; public static final Enum FALL; public static final Enum WINTER; private static final Enum $VALUES[]; static { SPRING = new Enum("SPRING", 0); SUMMER = new Enum("SUMMER", 1); FALL = new Enum("FALL", 2); WINTER = new Enum("WINTER", 3); $VALUES = (new Enum[] { 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; }
-
注意此处继承之后的桥接方法
-
同时,我们需要知道因为类型擦除而出现的错误,详见泛型
内部类
多态
-
原始代码
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(); } }