java 反编译项目

大家好,该是从2012年开始写作的时候了。正如您在其他博客中可能已经看到的那样,有一些更改可以使您使用Java编程时的开发人员生活变得更加轻松:Diamond运算符,Switchs中的Strings,尝试使用资源,多次捕获等

在本文(PART I)中,我们将看到Java 7 Project Coin(JSR 334)中提出的一些小改动,然后(在第二部分中)我们将对它们进行反编译,以查看编译器在做什么(对于仅用于教育目的)。

你需要什么

  • NetBeans 7+或任何其他支持Java 7的IDE
  • JSDK 7+
  • JAD反编译 [R 或 Java的反编译

钻石算子

泛型帮助我们减少了ClassCastExceptions,但是有时候它会使代码难以阅读。 钻石算子是一个非常不错的变化。 成像您需要按城市对客户进行分组。 您将需要以下内容:

//suppose the classes City and Customer exist
...
Map<City,List<Customer>> map = new
HashMap<City,List<Customer>>();
...

现在,如果您还需要按国家/地区对数据进行分组怎么办:

//suppose the classes Country, City and Customer exist
...
Map<Country,MapltCity,List<Customer>>> map = new HashMapl&t;Country,MapltCity,ListltCustomer>>>();
...

现在,它开始变得很难阅读,对吧? 如果您还需要按地区分组怎么办?

//suppose the classes Region, Country, City and Customer exist
...
Map<Region,Map<Country,Map<City,List<Customer>>>> map = new HashMap<Region, Map<Country,Map<City,List<Customer>>>>();
...

所以你怎么看? 读取这样的代码根本不容易。 幸运的是,新的Diamond运算符对代码的可读性有很大帮助。 最后的代码可以在Java 7中重新编码,如下所示:

//suppose the classes Region, Country, City and Customer exist
...
Map<Region,Map<Country,Map<City,List<Customer>>>> map = new HashMap<>();
...

好了很多!

开关中的弦

我已经等了很多!!! 我还记得我刚开始Java时代的日子,我确实需要在switch中使用Strings。 好吧,我的等待终于结束了。 在Java的早期版本中,您必须编写如下代码:

//in a class
...
public void stringToNumber(String str)
{if(str.equalsIgnoreCase("one")){System.out.println(1);}else if(str.equalsIgnoreCase("two")){System.out.println(2);}else if(str.equalsIgnoreCase("three")){System.out.println(3);}
}
...

在Java 7中,您可以这样编写:

//in a class
...
public void stringToNumber(String str)
{switch(str){case "one":System.out.println(1);break;case "two":   System.out.println(2);break;   case "three":System.out.println(3);break;}
}
...

甚至NetBeans也可以选择自动转换:

尝试使用资源和多重捕获

在此版本中,这是一个不错的增强,现在您不必担心关闭那些ResultSet,States,FileInputStreams等。 您只需要使用新的try结构,编译器就会为您处理它。 您甚至可以通过新的try结构将自己的类创建为Closeable(这是一个新接口)。 以下是通过流进行的经典文件访问:

//in a class
import java.io.*;
...
public static void copyFile(String path) throws IOException, NullPointerException
{File file = new File(path);FileOutputStream fout = null;FileInputStream fin = null;try {try {fout = new FileOutputStream("file.dat");fin = new FileInputStream(file);byte[] bytes = new byte[1024];int leido = 0;while ((leido = fin.read(bytes)) != -1) {fout.write(bytes, 0, leido);}} finally {if (fout != null) {fout.close();}if (fin != null) {fin.close();}}} catch (NullPointerException ex) {ex.printStackTrace();throw ex;}catch (IOException ex) {ex.printStackTrace();throw ex;}}
...

如果您注意到了,为了确保打开的流一旦完成就被关闭,则必须编写一个try / finally块并自己关闭它们。 在Java 7中,可以使用新的try结构和新的NIO.2类以更好的方式和更少的代码行实现相同的行为:

//in a class
import java.nio.file.*;
import java.io.*;
...
public static void copyFile(String src) throws IOException, NullPointerException
{Path path = FileSystems.getDefault().getPath(src);try (FileOutputStream fout = new FileOutputStream("file.dat")) {Files.copy(path, fout);} catch (NullPointerException | IOException ex) {ex.printStackTrace();throw ex;}
}
...

二进制文字和下划线

现在,您可以将整数表示为二进制文字,这在编程低级API时非常理想,还可以使用下划线以使您的值更易读:

//in a class
...
public static void coin()
{int binaryNum = 0b10; //This is number 2 in binary codedouble value1 = 1000000000; //hard to read?double value2 = 1_000_000_000; //Easy to read with Java 7double value3 = 0b101010110111; //hard to read?double value4 = 0b1010_1011_0111; //Easy to read with Java 7double pi = 3.14_15_92; //another example of readability
}
...

因此,更少的代码,更高的生产率和更好的代码可读性是Project Coin的宗旨! (除了这里没有看到的其他东西)。

钻石算子

这是我们在上一篇文章中刚刚看到的钻石操作员的示例:

//suppose the classes Region, Country, City and Customer exist
import java.util.*;
...
Map<region,map<country,map<city,list>>> map = new HashMap<>();
...</region,map<country,map<city,list

现在,让我们看看编译器生成的代码是什么样的:

import java.util.*;
...
java.util.Map map = new HashMap();
...

只是一个旧学校地图的定义和实例化...为什么? 因为这就是泛型的工作方式:

When you take an element out of a Collection, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection's type, so the cast can fail at run time.Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.

这意味着编译器将在编译时检查您是否使用了正确的类,并将任何必要的强制转换添加到生成的类中。 例如:

//suppose the classes Region, Country, City and Customer exist
import java.util.*;
...
Map<region,map<country,map<city,list>>> map = new HashMap<>();
Map<country,map<city,list>> m = map.get(new Region());
...
</country,map<city,list</region,map<country,map<city,list

您将获得如下内容:

//suppose the class Region exists
import java.util.*;
...
Map map = new HashMap();
Map m = (Map)map.get(new Region()); //the compiler added the cast
...

开关中的弦

记住上一篇文章中介绍的Strings in switch示例:

//in a class
...
public void stringToNumber(String str)
{switch(str){case "one":System.out.println(1);break;case "two":   System.out.println(2);break;   case "three":System.out.println(3);break;}
}
...

反编译之后,您会注意到开关状态菜单现在如何支持字符串:

//in a class
...
public static void stringInSwitch(String str)
{String s = str;byte byte0 = -1;switch(s.hashCode()){case 110182: if(s.equals("one"))byte0 = 0;break;case 115276: if(s.equals("two"))byte0 = 1;break;case 110339486: if(s.equals("three"))byte0 = 2;break;}switch(byte0){case 0: // ''System.out.println(1);break;case 1: // '01'System.out.println(2);break;case 2: // '02'System.out.println(3);break;}
}
...

是的……这是一个小技巧。 并不是直接在switch语句中支持字符串,而是它们的hashCodes是(hashCodes是整数)。 通过查看代码,我意识到最好不要在switch语句中使用Strings,因为最后,您将获得两个switch语句……

尝试使用资源和多重捕获

记住上一篇文章中的尝试资源和多捕获示例:

//in a class
import java.nio.file.*;
import java.io.*;
...
public static void copyFile(String src) throws IOException, NullPointerException
{Path path = FileSystems.getDefault().getPath(src);try (FileOutputStream fout = new FileOutputStream("file.dat")) {Files.copy(path, fout);} catch (NullPointerException | IOException ex) {ex.printStackTrace();throw ex;}
}
...

此示例在一个示例中使用try资源,并进行多捕获。 当我尝试使用JAD Java Decompiler对生成的类进行反编译时,我对嵌套的try语句有很多误解,因此我决定尝试JD Java Decompiler,结果如下:

//in a class
import java.nio.file.*;
import java.io.*;
...
public static void copyFile(String src) throws IOException, NullPointerException
{Path path = FileSystems.getDefault().getPath(src, new String[0]);try {FileOutputStream fout = new FileOutputStream("file.dat"); Throwable localThrowable2 = null;try { Files.copy(path, fout);}catch (Throwable localThrowable1){localThrowable2 = localThrowable1; throw localThrowable1;} finally {if (fout != null) { //I added this { symbol for readabilityif (localThrowable2 != null) { //I added this { symbol for readabilitytry { fout.close(); } catch (Throwable x2) { localThrowable2.addSuppressed(x2); } } //I added this } symbol for readabilityelse { //I added this { symbol for readabilityfout.close();  } //I added this } symbol for readability} //I added this } symbol for readability}} catch (IOException ex) {ex.printStackTrace();throw ex;}
}
...

从最后一段代码中,我们可以看到编译器如何使用新的(JDK 7) + addSuppressed(Throwable):void类Throwable来确保复制过程中抛出的任何异常都不会丢失。 这很重要,因为在应用程序中查找错误时,您将需要所有可能的异常。 另外,请注意,所有关闭操作都是在finally语句中完成的,以确保在过程结束时始终关闭资源。

二进制文字和下划线

我认为您可以弄清楚反编译此最后一个功能后会得到什么……

//in a class
...
public static void coin()
{int binaryNum = 0b10; //This is number 2 in binary codedouble value = 1000000000; //hard to read?double value = 1_000_000_000; //Easy to read with Java 7double value = 0b101010110111; //hard to read?double value = 0b1010_1011_0111; //Easy to read with Java 7double pi = 3.14_15_92; //another example of readability
}
...

是的,没有什么新东西了……编译器只重写没有下划线的值,并将二进制值转换为整数值:

//in a class
...
public static void coin(
{int binaryNum = 2;double value1 = 1000000000D;double value2 = 1000000000D;double value3 = 2743D;double value4 = 2743D;double pi = 3.1415920000000002D;
}
...

好的,仅此而已。 希望大家都喜欢Java 7中的Project Coin(JSR334)的新功能。Java8中的Project Coin II还有更多改进,我们将在以后的文章中进行检查。 拜拜!

参考:我们的JCG合作伙伴提供的 Java –项目硬币反编译和Java 7 –项目硬币反编译第二部分 Java和ME博客上的Alexis Lopez。

翻译自: https://www.javacodegeeks.com/2012/04/java-7-project-coin-decompiled.html

java 反编译项目

java 反编译项目_Java 7 –反编译项目硬币相关推荐

  1. java里面取反 怎么用_java 取反学习

    问题 最近学习java 位操作,取反运算遇到了问题. public class bitMpt { public static void main(String[] args) { int a = 12 ...

  2. java wrapper怎么运行_java wrapper方式部署项目

    java项目部署的方式多种多样,目前springboot框架下都是自带tomcat等服务运行环境的,也可以直接将编译包后的jar包解压后运行起来,今天要介绍的是用wrapper的方式部署项目,这种方式 ...

  3. 反射在java中的应用_java反射机制在项目中的运用

    定义:Reflection是java开发语言特性之一,它允许运行中的java程序对自身进行检测,自审,并能操作程序内部的属性和方法,Reflection是java被视为动态语言关键之一.允许程序从执行 ...

  4. java 二嗨租车项目_Java实现“汽车租赁项目”

    1.创建租车cab父类(抽象) package study; //创建抽象租车cab父类 public abstract class cab { //创建cab具有的公共属性 private Stri ...

  5. java和opencv配置_Java——OpenCVWindows配置和项目中jar包的简单配置

    1. 安装OpenCV 1.1 下载相应的OpenCV版本,解压 1.2 将 openCV的dll文件(D:\InstallPackages\OpenCV\opencv\build\java\x64) ...

  6. java电商和企业项目_java电商和企业项目

    这里比较的都是国外的开源项目,备选项目有: Smilehouse Workspace.Pulse.Shopizer.ofbiz.bigfish.broadleaf1.Smilehouse Worksp ...

  7. java程序设计实训项目_Java程序设计教程与项目实训

    本书以现代教育理念为指导,在讲授方式上注意结合应用开发实例,注重培养学生理解面向对象程序设计思想,以提高分析问题和解决实际问题的能力.采用由浅入深.理论与实践相结合的教学思路,通过大量的实例阐述Jav ...

  8. java实现atm取款_java实现ATM取款项目

    项目要求: 1.用户需要从控制台输入账号密码,账号或者密码不正确报异常 2.每日取款的金额有限制(100,30000),否则报异常 3.每次取款都要有记录,并在下一次取款时显示出来 思路: 1.先在& ...

  9. java程序设计教程与项目_Java程序设计教程与项目实训

    书名:Java程序设计教程与项目实训 作者:温秀梅.司亚超 出版社:清华大学出版社 出版日期:2017/8/1 字数: 页数: 版次: ISBN:9787#302473701 定价:49.5 目录 章 ...

最新文章

  1. VR/AR行业发展至今,它的市场规模如何
  2. 内核数据结构之红黑树
  3. python stm32-STM32F4系列使用MicroPython开发
  4. 二十万字!耗时90天
  5. 压缩文件拷到服务器损坏,压缩文件导致无法拷贝共享
  6. 爱数之介质服务器及介质同步技术
  7. YFIOServer 后台IO接口使用说明
  8. leetcode :数组和链表
  9. python旋转坐标系_python实现一个点绕另一个点旋转后的坐标
  10. mongodb多条件查询
  11. kubernetes kubeadm init this version of kubeadm only supports deploying clusters kubeadm版本降级
  12. AngularJS与服务器交互(4)
  13. Mybatis学习文档
  14. 关于Hyper-V设置了本地桥接网络后 宿主机网络变慢的问题
  15. JAVA获取服务器上的图片信息
  16. 贾又福大象鸿蒙,2016贾又福工作室师生优秀作品全国巡展
  17. 微信小程序 微信授权登录 微信登录
  18. 南京原市长季建业受贿1132万获刑15年
  19. Linux下学习DB2命令的笔记
  20. 边缘计算网关 5G/4G物联网工业互联

热门文章

  1. nginx部署laravel需要修改的配置
  2. 已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出两个集合A和集合B的差集(近由在A中出现而不再B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。
  3. 2020蓝桥杯省赛---java---B---1(门牌制作)
  4. 区间数多属性决策matlab,区间数多属性决策的改进理想解法
  5. kafka消费者开发方式小结
  6. aws 删除ec2实例_如何在AWS中启动EC2实例
  7. java序列化和反序列化_Java恶意序列化背后的历史和动机
  8. java使用迭代器删除元素_使用Java从地图中删除元素
  9. envoy api 网关_在边缘,作为网关或在网格中构建控制平面以管理Envoy代理的指南...
  10. 对称密钥加密算法 对称轮数_选择Java加密算法第2部分–单密钥对称加密