zoukankan      html  css  js  c++  java
  • Java 7 中的Switch 谈 Java版本更新和反编译知识

    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命令,可以运行

     

             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: // ''

                s2 = (new StringBuilder()).append(s).append("u5148u751F").toString();

                break;

            case 1: // '01'

                s2 = (new StringBuilder()).append(s).append("u5973u58EB").toString();

                break;

            default:

                s2 = s;

                break;

            }

            return s2;

        }

    }

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

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

            

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

    追寻梦的飞飞

    2014.04.02 于广州

  • 相关阅读:
    机器学习分类
    12.python中高阶函数以及内建函数(map,filter,sorted),和闭包
    python中的异常处理相关语句和迭代器
    和好朋友渐行渐远是什么感觉?
    MDX学习笔记(整理) MDX语法
    Cognos软件介绍文档(原创)
    隐藏
    android::Mutex::Autolock的使用
    Android中sp和wp的使用
    Day 07 字符编码,文件操作
  • 原文地址:https://www.cnblogs.com/hbhzsysutengfei/p/3640313.html
Copyright © 2011-2022 走看看