当前位置: 首页 > news >正文

内容营销方案百度seo关键词优化排名

内容营销方案,百度seo关键词优化排名,怎么用本机做服务器发布网站,区政府网站集约化建设3. 编译期处理 什么是语法糖 所谓的 语法糖 ,其实就是指 java 编译器把 *.java 源码编译为 *.class 字节码的过程中,自动生成 和转换的一些代码,主要是为了减轻程序员的负担,算是 java 编译器给我们的一个额外福利(给…

3. 编译期处理

什么是语法糖

所谓的 语法糖 ,其实就是指 java 编译器把 *.java 源码编译为 *.class 字节码的过程中,自动生成 和转换的一些代码,主要是为了减轻程序员的负担,算是 java 编译器给我们的一个额外福利(给糖吃)

以下代码分析的前提

注意,以下代码的分析,借助了 javap 工具、idea 的反编译功能、idea 插件、jclasslib 等工具。另外, 编译器转换的结果直接就是 class 字节码,只是为了便于阅读,给出了 几乎等价 的 java 源码方式,并不是编译器还会转换出中间的 java 源码,切记。

3.1 默认构造器

public class Candy1 {
}

编译成class后的代码:

public class Candy1 {// 这个无参构造是编译器帮助我们加上的public Candy1() {super(); // 即调用父类 Object 的无参构造方法,即调用 java/lang/Object."
<init>":()V}
}

3.2 自动拆装箱

这个特性是 JDK 5 开始加入的, 代码片段1 :

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

这段代码在 JDK 5 之前是无法编译通过的,必须改写为 代码片段2 :

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

        显然之前版本的代码太麻烦了,需要在基本类型和包装类型之间来回转换(尤其是集合类中操作的都是包装类型),因此这些转换的事情在 JDK 5 以后都由编译器在编译阶段完成。即 代码片段1 都会在编 译阶段被转换为 代码片段2

3.3 泛型集合取值

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

public class Candy3 {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);}
}

所以在取值时,编译器真正生成的字节码中,还要额外做一个类型转换的操作:

// 需要将 Object 转为 Integer
Integer x = (Integer)list.get(0)

如果前面的 x 变量类型修改为 int 基本类型那么最终生成的字节码是:

// 需要将 Object 转为 Integer, 并执行拆箱操作
int x = ((Integer)list.get(0)).intValue();

擦除的是字节码上的泛型信息,可以看到 LocalVariableTypeTable 仍然保留了方法参数泛型的信息

public cn.itcast.jvm.t3.candy.Candy3();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."
<init>":()V4: returnLineNumberTable:line 6: 0LocalVariableTable:Start Length Slot Name Signature0     5     0   this Lcn/itcast/jvm/t3/candy/Candy3;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=3, args_size=10: new #2 // class java/util/ArrayList3: dup4: invokespecial #3 // Method java/util/ArrayList."
<init>":()V7: astore_18: aload_19: bipush 1011: invokestatic #4 // Method
java/lang/Integer.valueOf:(I)Ljava/lang/Integer;14: invokeinterface #5, 2 // InterfaceMethod
java/util/List.add:(Ljava/lang/Object;)Z19: pop20: aload_121: iconst_022: invokeinterface #6, 2 // InterfaceMethod
java/util/List.get:(I)Ljava/lang/Object;27: checkcast #7 // class java/lang/Integer30: astore_231: returnLineNumberTable:line 8: 0line 9: 8line 10: 20line 11: 31LocalVariableTable:Start Length Slot Name Signature0     32     0   args [Ljava/lang/String;8     24     1   list Ljava/util/List;LocalVariableTypeTable:Start Length Slot Name Signature8    24     1   list Ljava/util/List<Ljava/lang/Integer;>;

使用反射,仍然能够获得这些信息:

public Set<Integer> test(List<String> list, Map<Integer, Object> map) {
}
Method test = Candy3.class.getMethod("test", List.class, Map.class);
Type[] types = test.getGenericParameterTypes();
for (Type type : types) {if (type instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) type;System.out.println("原始类型 - " + parameterizedType.getRawType());Type[] arguments = parameterizedType.getActualTypeArguments();for (int i = 0; i < arguments.length; i++) {System.out.printf("泛型参数[%d] - %s\n", i, arguments[i]);}}
}

输出

原始类型 - interface java.util.List
泛型参数[0] - class java.lang.String
原始类型 - interface java.util.Map
泛型参数[0] - class java.lang.Integer
泛型参数[1] - class java.lang.Object

3.4 可变参数

可变参数也是 JDK 5 开始加入的新特性:

Java代码

public class Candy4 {public static void foo(String... args) {String[] array = args; // 直接赋值System.out.println(array);}public static void main(String[] args) {foo("hello", "world");}
}

被编译器转换后的代码

可变参数 String... args 其实是一个 String[] args ,从下面的代码中就可以看出来

public class Candy4 {public static void foo(String[] args) {String[] array = args; // 直接赋值System.out.println(array);}public static void main(String[] args) {foo(new String[]{"hello", "world"});}
}

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

3.5 foreach 循环

仍是 JDK 5 开始引入的语法糖

1.数组的 foreach 循环

Java代码

public class Candy5_1 {public static void main(String[] args) {int[] array = {1, 2, 3, 4, 5}; // 数组赋初值的简化写法也是语法糖哦for (int e : array) {System.out.println(e);}}
}

被编译器转换后的代码

public class Candy5_1 {public Candy5_1() {}public static void main(String[] args) {int[] array = new int[]{1, 2, 3, 4, 5};for(int i = 0; i < array.length; ++i) {int e = array[i];System.out.println(e);}}
}

2.集合的 foreach 循环

Java代码

public class Candy5_2 {public static void main(String[] args) {List<Integer> list = Arrays.asList(1,2,3,4,5);for (Integer i : list) {System.out.println(i);}}
}

被编译器转换后的代码

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

public class Candy5_2 {public Candy5_2() {}public static void main(String[] args) {List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);Iterator iter = list.iterator();while(iter.hasNext()) {Integer e = (Integer)iter.next();System.out.println(e);}}
}

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

3.6 switch

字符串从 JDK 7 开始,switch 可以作用于字符串和枚举类,这个功能其实也是语法糖

1. switch 字符串

Java代码

public class Candy6_1 {public static void choose(String str) {switch (str) {case "hello": {System.out.println("h");break;}case "world": {System.out.println("w");break;}}}
}

注意 switch 配合 String 和枚举使用时,变量不能为null,原因分析完语法糖转换后的代码应当自然清楚

被编译器转换后的代码

public class Candy6_1 {public Candy6_1() {}public static void choose(String str) {byte x = -1;switch(str.hashCode()) {case 99162322: // hello 的 hashCodeif (str.equals("hello")) {x = 0;}break;case 113318802: // world 的 hashCodeif (str.equals("world")) {x = 1;}}switch(x) {case 0:System.out.println("h");break;case 1:System.out.println("w");}}
}

可以看到,执行了两遍 switch,第一遍是根据字符串的 hashCode 和 equals 将字符串的转换为相应 byte 类型,第二遍才是利用 byte 执行进行比较。

为什么第一遍时必须既比较 hashCode,又利用 equals 比较呢?hashCode 是为了提高效率,减少可能的比较;而 equals 是为了防止 hashCode 冲突,例如 BM 和 C,这两个字符串的hashCode值都是 2123 ,如果有如下Java代码:

public class Candy6_2 {public static void choose(String str) {switch (str) {case "BM": {System.out.println("h");break;}case "C.": {System.out.println("w");break;}}}
}

被编译器转换后的代码

public class Candy6_2 {public Candy6_2() {}public static void choose(String str) {byte x = -1;switch(str.hashCode()) {case 2123: // hashCode 值可能相同,需要进一步用 equals 比较if (str.equals("C.")) {x = 1;} else if (str.equals("BM")) {x = 0;}default:switch(x) {case 0:System.out.println("h");break;case 1:System.out.println("w");}}}
}

2.switch 枚举

Java代码

enum Sex {MALE, FEMALE
}
public class Candy7 {public static void foo(Sex sex) {switch (sex) {case MALE:System.out.println("男"); break;case FEMALE:System.out.println("女"); break;}}
}

被编译器转换后的代码

public class Candy7 {/*** 定义一个合成类(仅 jvm 使用,对我们不可见)* 用来映射枚举的 ordinal 与数组元素的关系* 枚举的 ordinal 表示枚举对象的序号,从 0 开始* 即 MALE 的 ordinal()=0,FEMALE 的 ordinal()=1*/static class $MAP {// 数组大小即为枚举元素个数,里面存储case用来对比的数字static int[] map = new int[2];static {map[Sex.MALE.ordinal()] = 1;map[Sex.FEMALE.ordinal()] = 2;}}public static void foo(Sex sex) {int x = $MAP.map[sex.ordinal()];switch (x) {case 1:System.out.println("男");break;case 2:System.out.println("女");break;}}
}

3.7 枚举类

http://www.yidumall.com/news/61203.html

相关文章:

  • 网站建设项目的网络图windows优化大师官方下载
  • web可以做3d网站吗网站推广优化排名教程
  • wordpress+修改邮箱设置北京网站优化对策
  • 网站内容页显示不出来百度关键词如何优化
  • 定制化网站一般价格百度指数移动版
  • 现在可以用的网站无锡seo网站管理
  • 做网站需要学习什么知识房地产十大营销手段
  • 河南省建设厅网站师林峰象山关键词seo排名
  • 免费自制网站建设福州seo网站推广优化
  • 做直播网站有哪些外贸新手怎样用谷歌找客户
  • 贵州网站建设维护企业查询系统官网天眼查
  • 网站开发毕业论文参考文献百度指数有什么作用
  • 做淘客网站要多大的服务器销售crm客户管理系统
  • Pc端做社区网站用什么框架今日疫情最新消息全国31个省
  • 备案网站域名查询找人帮忙注册app推广
  • 网站咨询弹窗是怎么做的最新新闻事件今天疫情
  • 网站做行业认证好处搜外seo
  • 怎么查在哪个网站做的备案谷歌浏览器官网下载手机版
  • 可以中英切换的网站怎么做怎样优化网站关键词排名靠前
  • 网站做SEO优化上海最新发布最新
  • 网站建设基本流程网络推广是以企业产品或服务
  • html css 教程seo和sem是什么
  • 淘宝网(淘宝网)温州seo排名优化
  • 用meteor框架做的微博网站今日足球最新预测比分
  • 大学网站建设技术方案百度在西安有分公司吗
  • 做vip兼职设计师的网站有哪些新产品推广方案范文
  • 政府网站建设应用工作方案重庆seo标准
  • 网站开发课设心得体会拉新app推广接单平台
  • 自己怎么做云购网站杭州seo网站推广排名
  • 织梦做的网站如何修改安徽建站