Java 7 中的Switch 谈 Java版本更新和反编译知识

时间:2022-09-10 21:49:24

Java 7 中的Switch 谈 Java版本更新和反编译知识

         学习编程,享受生活,大家好,我是追寻梦的飞飞。今天主要讲述的是Java7中的更新Switch实现内部原理和JAD反编译知识,反编译很好玩的!

Java语言大版本之间的更新,会添加一些比较好的改动。目前最流行的应该是Java7 版本的,现在java 8 已经推出,更多的是关注与移动互联网领域,比如位置信息、触摸即使、罗盘指针、重力感应之类的。不过到java 8 推广还有一段时间,所以就先学习Java7中的新改动的知识了。软件版本更新需要考虑对之间版本的兼容性,让版本更新的代价最小,这一点在Switch中是如何体现的呢?

之前的Java中Switch仅仅支持整形的数据,所以给编程带来一定的困扰,极大的限制了程序的灵活性(我想说的是C/C++中好像也是仅仅支持类int类型的变量)。但是在Java7中增加了一种String类型,Switch语句支持Character Byte Short Integer String类型。但是这一种方式的改变,在底层如何实现,怎样修改使得代价最小:

在Switch语句中,case中的值是不可以相等的,经过编译之后的Java代码会全部转为Unicode字符:所以下面的情况是不会通过编译的:

String gender  = “”;

switch(gender){

case “男”:

break;

case “\u7537”:

break;

}

这样的代码是不会被编译通过的。因为unicode中的\u7537就是汉字男

在底层的实现原理:

因为之前的Switch是仅仅支持int类型的,也就是说在JVM和字节码层次上仅仅支持int类型的变量,那么减少这个改变带来的影响,就需要根据源代码中的含义,将字符串转变为对应的int值,不同的JAVA编译器采用不同的方式进行转变,这里我们想到的就是Java的hashCode。

这里就需要介绍一个很好的工具JAD,它可以反编译,也就是把字节码编译成为Java源代码,好像很厉害的样子,于是我就忍不住,赶紧来试一下,如果可以反编译别人的字节码,那岂不是碉堡了,在反编译之前,我们先大胆的猜一下:Java的反编译应该是比C/C++的要简单的多,因为JVM 的标准是开放的,所以生成的字节码也是有规律的,但是反编译之后的源代码应该和自己写的源代码有一定的差别,但是差别会有多大,感觉不会很大。因为每一个JAVA文件是独自的编译的,生成对应的字节码。我们测试一下:

首先是下载工具和配置环境了:很小的几百k,加压出来发现就两个文件执行exe和说明文档。为了能够在命令行中可以运行,我们直接把她放在JDK/bin中,前提是你配置了JAVA环境变量。

开始测试了:

1.输入jad命令,可以运行

Java 7 中的Switch 谈 Java版本更新和反编译知识

2.找个自己的源代码

TestMain.java

import java.io.InputStream;

import net.sf.ehcache.Cache;

import net.sf.ehcache.CacheManager;

import org.eclipse.jetty.server.Connector;

import org.eclipse.jetty.server.Handler;

import org.eclipse.jetty.server.Server;

import org.eclipse.jetty.server.ServerConnector;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yang.lolvideo.jetty.handler.LolHandler;

public class TestMain {

private static final int PORT_ONE = 8087;

private static final int PORT_TWO = 8088;

public static void main(String[] args) throws Exception {

// TODO Auto-generated method stub

//Spring config

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

//ehcache config to get the object cache

InputStream ehcacheConfig = TestMain.class.getResourceAsStream("ehcache.xml");

CacheManager cacheManager = CacheManager.create(ehcacheConfig);

Cache cache = cacheManager.getCache("sampleCache1");

//Jetty server to run the server

Server server =new Server();

ServerConnector connector_one = new ServerConnector(server);

connector_one.setPort(PORT_ONE);

ServerConnector connector_two = new ServerConnector(server);

connector_two.setPort(PORT_TWO);

server.setConnectors(new Connector[]{connector_two});

Handler handler = new LolHandler(context,cache);

server.setHandler(handler);

//start server

server.start();

server.join();

}

}

将他的字节码反编译

jad –p TestMain.class > TestMain.java // 将编译的结果重定向到文件

jad –p TestMain.class // 将编译的结果显示在屏幕

jad –o TestMain.class > TestMain.java // 不提示,直接覆盖原文件

查看源文件:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.

// Jad home page: http://www.kpdus.com/jad.html

// Decompiler options: packimports(3)

// Source File Name:   TestMain.java

import com.yang.lolvideo.jetty.handler.LolHandler;

import net.sf.ehcache.CacheManager;

import org.eclipse.jetty.server.*;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMain

{

public TestMain()

{

}

public static void main(String args[])

throws Exception

{

org.springframework.context.ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

java.io.InputStream ehcacheConfig = TestMain.getResourceAsStream("ehcache.xml");

CacheManager cacheManager = CacheManager.create(ehcacheConfig);

net.sf.ehcache.Cache cache = cacheManager.getCache("sampleCache1");

Server server = new Server();

ServerConnector connector_one = new ServerConnector(server);

connector_one.setPort(8087);

ServerConnector connector_two = new ServerConnector(server);

connector_two.setPort(8088);

server.setConnectors(new Connector[] {

connector_two

});

org.eclipse.jetty.server.Handler handler = new LolHandler(context, cache);

server.setHandler(handler);

server.start();

server.join();

}

private static final int PORT_ONE = 8087;

private static final int PORT_TWO = 8088;

}

果然是超厉害,这反编译的写的代码比我自己的源代码更加规范,我和我的小伙伴们的哦惊呆了,这样岂不是可以……你懂的

还是回来说说这些switch实现的机制:

源代码是:

//TestMain.java

public class TestMain

{

public String generatee(String name, String gender){

String title="";

switch(gender){

case "男":

title= name + "先生";

break;

case "女":

title=name+ "女士";

break;

default:

title = name;

}

return title;

}

}

反编译之后:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.

// Jad home page: http://www.kpdus.com/jad.html

// Decompiler options: packimports(3)

// Source File Name:   TestMain.java

public class TestMain

{

public TestMain()

{

}

public String generatee(String s, String s1)

{

String s2 = "";

String s3 = s1;

byte byte0 = -1;

switch(s3.hashCode())

{

case 30007:

if(s3.equals("\u7537"))

byte0 = 0;

break;

case 22899:

if(s3.equals("\u5973"))

byte0 = 1;

break;

}

switch(byte0)

{

case 0: // '\0'

s2 = (new StringBuilder()).append(s).append("\u5148\u751F").toString();

break;

case 1: // '\001'

s2 = (new StringBuilder()).append(s).append("\u5973\u58EB").toString();

break;

default:

s2 = s;

break;

}

return s2;

}

}

在底层原来是这样实现的,在转变为hashCode之后,也会在内部使用equal函数进行判断。因为不同的对象产生的hashCode也会有相等的时候。在这里吧他们转变为byte的0,1,2,之后在来一个switch进行判断,执行对应的操作。

所以说在在底层执行代码不一定就是我们编写的代码,这个时候我们就应给考虑执行效率的问题。如果对于这种switch我们可以尝试使用enum类型来进行优化。

今天就先到这里了,不断的学习新的技术,和大家分享!

追寻梦的飞飞

2014.04.02 于广州

Java 7 中的Switch 谈 Java版本更新和反编译知识的更多相关文章

  1. .NET中使用switch和java不一样的地方。

    1.不能这样贯穿 我们知道,java 和 C在使用switch时候可以这样. switch (i) { //java中此处不使用break // 执行了case 1:对应的语句后直接 贯穿到 case ...

  2. java switch case 枚举类型的反编译结果

     package com.example.demo; import java.io.PrintStream;  // Referenced classes of package com.example ...

  3. 对Java代码加密的两种方式,防止反编译

    使用Virbox Protector对Java项目加密有两种方式,一种是对War包加密,一种是对Jar包加密.Virbox Protector支持这两种文件格式加密,可以加密用于解析class文件的j ...

  4. 浅谈java中异常抛出后代码是否会继续执行

    问题 今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element) ...

  5. HAL中通过JNI调用java方法【转】

    转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...

  6. Intellij Idea 工具在java文件中如何避免 import .*包

    Intellij Idea工具在java文件中怎么避免import java.utils.*这样的导入方式,不推崇导入*这样的做法!Editor->Code Style->Java-&gt ...

  7. 关于Java运算中类型自动提升的问题

    1.表达式中的自动类型提升: 表达式求值时,Java自动的隐含的将每个byte.short或char操作数提升为int类型,这些类型的包装类型也是可以的. 例如:short s1 = 1; s1 =  ...

  8. Java 8 中的 Streams API 详解

    为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...

  9. Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置

    一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...

随机推荐

  1. WampServer 的phpmyadmin数据

    WampServer首次安装的时候phpmyadmin的密码是为空 设置密码 1.安装成功后,通过 phpmyadmin 进入mysql,点击上面的 [用户] 菜单,在用户[root]主机[local ...

  2. 设计模式C#实现(一)——模板方法模式

    模板方法模式——在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重写定义算法中的某些步骤. 假如我们有两种咖啡因饮料:茶和咖啡.茶的制作过程为: ...

  3. 利用百度地图API,在浏览器中找到自己的位置

    首先你得有个百度地图的秘钥,http://lbsyun.baidu.com/apiconsole/key 剩下的就是编码了 这里面会用到一个javascript里的一个函数,getMyLocation ...

  4. SQL中EXISTS和IN用法

    SQL中EXISTS的用法  指定一个子查询,检测行的存在. 语法:EXISTS subquery 参数:subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INT ...

  5. CTreeCtrl结点拖动实现(与后台联动)

    原帖及讨论:http://bbs.bccn.net/thread-211413-1-1.html 效果描述:鼠标点击并拖动某一结点可以把它以动到其他结点下.原理:把一个结点机器下面的所有结点在需要释放 ...

  6. 【转】Oracle修改表空间为自动扩展

    1.数据文件自动扩展的好处1)不会出现因为没有剩余空间可以利用到数据无法写入2)尽量减少人为的维护3)可以用于重要级别不是很大的数据库中,如测试数据库等 2.数据文件自动扩展的弊端1)如果任其扩大,在 ...

  7. POJ 1002 UVA 755 487--3279 电话排序 简单但不容易的水题

    题意:给你许多串字符串,从中提取电话号码,输出出现复数次的电话号码及次数. 以下是我艰难的AC历程:(这题估计是我刷的题目题解次数排前的了...) 题目不是很难理解,刚开始想到用map,但stl的ma ...

  8. Mongodb内嵌数组的完全匹配查询

    样例数据: {      "cNo" : "11",     "Details" : [         {              &q ...

  9. Java的Start和Runnable方法的区别

    两种方法的区别 1) start:用法:start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码.通过调用Thread类的start()方法来启动一 ...

  10. mutex 实现 只允许一个进程

    static class Program { [STAThread] static void Main() { bool createdNew=false; Mutex mutex = new Mut ...