语法糖(Syntactic Sugar),也称糖衣语法,指在计算机语言中添加的某种语法,这种语法对语言本身功能来说没有什么影响,只是为了方便程序员的开发,提高开发效率。说白了,语法糖就是对现有语法的一个封装。


泛型

java泛型学习笔记

java泛型擦除和泛型重载

java的PECS原则

自动装箱、拆箱和循环遍历(Foreach)

示例代码:

import java.util.List;

import java.util.ArrayList;

public class JavaCandy{

public static void main(String[]args){

List<Integer> list=new ArrayList<Integer>();

list.add(1);

list.add(2);

list.add(3);

int sum=0;

for(int i:list){

sum+=i;

}

System.out.println(sum);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

反编译class

import java.io.PrintStream;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

public class JavaCandy

{

public static void main(String[] paramArrayOfString)

{

ArrayList localArrayList = new ArrayList();

localArrayList.add(Integer.valueOf(1));

localArrayList.add(Integer.valueOf(2));

localArrayList.add(Integer.valueOf(3));

int i = 0;

for (Iterator localIterator = localArrayList.iterator(); localIterator.hasNext();)

{

int j = ((Integer)localIterator.next()).intValue();

i += j;

}

System.out.println(i);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

结果分析:

看到自动调用了以下语句:

localArrayList.add(Integer.valueOf(1));//装箱

int j = ((Integer)localIterator.next()).intValue();//拆箱

1

2

自动装箱拆箱的陷阱

实例代码:

public class JavaCandy{

public static void main(String[]args){

Integer a=1;

Integer b=2;

Integer c=3;

Integer d=3;

Integer e=321;

Integer f=321;

Long g=3L;

System.out.println(c==d);

System.out.println(e==f);

System.out.println(c==(a+b));

System.out.println(c.equals(a+b));

System.out.println(g==(a+b));

System.out.println(g.equals(a+b));

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

反编译代码:

import java.io.PrintStream;

public class JavaCandy

{

public static void main(String[] paramArrayOfString)

{

Integer localInteger1 = Integer.valueOf(1);

Integer localInteger2 = Integer.valueOf(2);

Integer localInteger3 = Integer.valueOf(3);

Integer localInteger4 = Integer.valueOf(3);

Integer localInteger5 = Integer.valueOf(321);

Integer localInteger6 = Integer.valueOf(321);

Long localLong = Long.valueOf(3L);

System.out.println(localInteger3 == localInteger4);

System.out.println(localInteger5 == localInteger6);

System.out.println(localInteger3.intValue() == localInteger1.intValue() + localInteger2.intValue());

System.out.println(localInteger3.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));

System.out.println(localLong.longValue() == localInteger1.intValue() + localInteger2.intValue());

System.out.println(localLong.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

输出结果

Integer.valueof()方法

public static Integer valueOf(int i) {

return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];

}

1

2

3

可以看到如果在(-128,128]的区间内的值就会直接从SMALL_VALUES数组中直接取值,如果大于这个范围就会新建一个类。

什么是SMALL_VALUES[i+128]

private static final Integer[] SMALL_VALUES = new Integer[256];

1

自动拆箱和装箱操作是一个耗费资源的过程,所以比较小的值就直接保存到内存里。

变长参数

示例代码:

public class JavaCandy{

public static void method(int...a){

for(int i:a)

System.out.println(i);

}

public static void main(String[]args){

System.out.println("this is method(1);");

method(1);

System.out.println("this is method(1,2);");

method(1,2);

System.out.println("this is method(1,2,3);");

method(1,2,3);

System.out.println("this is method(1,2,3,4);");

method(1,2,3,4);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

反编译结果

import java.io.PrintStream;

public class JavaCandy

{

public static void method(int... paramVarArgs)

{

for (int k : paramVarArgs) {

System.out.println(k);

}

}

public static void main(String[] paramArrayOfString)

{

System.out.println("this is method(1);");

method(new int[] { 1 });

System.out.println("this is method(1,2);");

method(new int[] { 1, 2 });

System.out.println("this is method(1,2,3);");

method(new int[] { 1, 2, 3 });

System.out.println("this is method(1,2,3,4);");

method(new int[] { 1, 2, 3, 4 });

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

可以看到此时参数自动变为数组类型。

条件编译

示例代码:

public class JavaCandy{

public static void main(String[]args){

if(true){

System.out.println("block1");

}else{

System.out.println("block2");

}

}

}

1

2

3

4

5

6

7

8

9

10

反编译结果:

import java.io.PrintStream;

public class JavaCandy

{

public static void main(String[] paramArrayOfString)

{

System.out.println("block1");

}

}

1

2

3

4

5

6

7

8

9

10

此时在if语句中会根据布尔值常量的真假,编译器会把分支中不成立的代码块消除掉。这一工作在编译器解除语法糖阶段完成。

只有if语句才有上面的效果,其他语句会显示拒绝编译。

比如:

public class JavaCandy{

public static void main(String[]args){

while(false){

System.out.println("block1");

}

}

}

1

2

3

4

5

6

7

8

输出结果:

java中类的定义使用class,枚举类的定义使用enum。在Java的字节码结构中,其实并没有枚举类型,枚举类型只是一个语法糖,在编译完成后被编译成一个普通的类。这个类继承java.lang.Enum,并被final关键字修饰。

枚举类型

枚举类型就是一些具有相同特性的类常量

java中类的定义使用class,枚举类的定义使用enum。在Java的字节码结构中,其实并没有枚举类型,枚举类型只是一个语法糖,在编译完成后被编译成一个普通的类。这个类继承java.lang.Enum,并被final关键字修饰。

public enum Fruit {

APPLE,ORINGE

}

1

2

3

使用jad对编译后的class文件进行反编译后得到:

public final class Fruit extends Enum

{

public static Fruit[] values()

{

return (Fruit[])$VALUES.clone();

}

public static Fruit valueOf(String s)

{

return (Fruit)Enum.valueOf(Fruit, s);

}

private Fruit(String s, int i)

{

super(s, i);

}

//枚举类型常量

public static final Fruit APPLE;

public static final Fruit ORANGE;

private static final Fruit $VALUES[];//使用数组进行维护

static

{

APPLE = new Fruit("APPLE", 0);

ORANGE = new Fruit("ORANGE", 1);

$VALUES = (new Fruit[] {

APPLE, ORANGE

});

}

}

---------------------

作者:uncle_gy