java反编译enum
A. java 编译过程中出现“需要为class,interface或enum”是什么意思本人自学JAVA不久!
Dog d=new Dog("wnagwang"."yellow",6);
随便看了一下 ,貌似yellow前面应该是,而不是.
还有
public class Dog{
String name1;
String color1;
int b;
}
Dog(String y1,String y2,int y3){
name1=y1;
color=y2;
b=y3
}
中你想写的应该是color1=y2吧
B. java编译错误 需要class interface或enum
这种问题很好避免,就是用编译软件编写程序。你这种问题一般是因为文件后缀名,文件夹,和public之中哪个出现问题了
C. 我反编译某个java代码,得到了一个枚举 ,如何才能反推出原始的枚举是怎么写的
里面有五个枚举值:
message,notify,count,Me,comment
D. android 反编译的enum类是这个样子,请高手指点下什么意思
enum在javac后会被编译成为一个静态数组。
所以反编译会变成如此,不用在意
E. Java 枚举型为什么是静态的,以及是怎么实现的
是的,Java枚举型是静态常量,隐式地用static final修饰过。
确切地说,Java枚举型是“静态常量”,这里面包含了两层意思:
枚举型中的实例隐式地用static final修饰过。
枚举型作为某个类中的成员字段也隐式地用static final修饰过。
public class Traffic{
public enum Light{GREEN,YELLOW,RED}
}
还是你上面这个代码,反编译一下,你就能看到--编译器背着你偷偷做了哪些手脚:
/*
* Decompiled with CFR 0_118.
*/
package com.ciaoshen.thinkinjava.chapter19;
public class Traffic {
public static final class Light
extends Enum<Light> {
public static final /* enum */ Light GREEN = new Light();
public static final /* enum */ Light YELLOW = new Light();
public static final /* enum */ Light RED = new Light();
private static final /* synthetic */ Light[] $VALUES;
public static Light[] values() {
return (Light[])$VALUES.clone();
}
public static Light valueOf(String string) {
return Enum.valueOf(Light.class, string);
}
private Light() {
super(string, n);
}
static {
$VALUES = new Light[]{GREEN, YELLOW, RED};
}
}
}
首先,枚举型Light是个实实在在的类。继承自基类Enum<Light>。然后在你不知情的情况下,偷偷加了static final修饰词。
然后三个枚举实例GREEN, YELLOW, RED也确确实实是Light的实例。然而前面也加上了static final。
然后构造器也被偷偷地阉割成private。这种实例控制手段,是不是在单例器模式里也见过?所以枚举也是实现单例器的一种方法。
然后编译器还偷偷合成了Light[]数组,一个values( )方法,一个valueOf( )方法。这个values( )在Enum的文档里都找不到。
如果在Enum里定义一个相关方法,你还会看到一个匿名内部类:
public enum Light{
GREEN{public void show(){System.out.println("Green");}},
YELLOW{public void show(){System.out.println("Yellow");}},
RED{public void show(){System.out.println("Red");}};
}
反编译的结果如下:
/*
* Decompiled with CFR 0_118.
*/
package com.ciaoshen.thinkinjava.chapter18;
import java.io.PrintStream;
public class Light
extends Enum<Light> {
public static final /* enum */ Light GREEN = new Light("GREEN", 0){
public void show() {
System.out.println("Green");
}
};
public static final /* enum */ Light YELLOW = new Light("YELLOW", 1){
public void show() {
System.out.println("Yellow");
}
};
public static final /* enum */ Light RED = new Light("RED", 2){
public void show() {
System.out.println("Red");
}
};
private static final /* synthetic */ Light[] $VALUES;
public static Light[] values() {
return (Light[])$VALUES.clone();
}
public static Light valueOf(String string) {
return Enum.valueOf(Light.class, string);
}
private Light() {
super(string, n);
}
static {
$VALUES = new Light[]{GREEN, YELLOW, RED};
}
}
总之,Java的Enum枚举型整个就是一个大大的“语法糖”。明明是一个完整的类,但只向用户暴露几个静态常量,隐藏掉大部分实现的细节。
F. Java枚举类型的问题
首先,我们看下枚举类的源码或java1.6 API文档就会发现这两个方法的定义分别为: public final String name() { return name; } public String toString() {return name; } 两个方法都是返回枚举类中的private final String name 。本质上没什么区别。 再次,我们看下该两个方法的定义,name()定义的是final String类型的,而toString()定义的是普通String类型的,这个就是你知道为什么toString()能重写,而name()不能重写。其实你问的还有没有其它的区别,区别也是在这里能重写与不能重写的区别,我们就写一个简单的例子来说明下: public class EnumTest{ public enum People{ Chinese("中国人"),American("美国人"); private String people ; private People(String people){ this.people = people ; } public String toString(){ return super.toString()+"("+people+")" ; } } public static void main(String[] args){ People people=People.Chinese; System.out.println("name->"+people.name()); System.out.println("toString->"+people.toString()); } } 打印出来的结果是: name->Chinese toString->Chinese(中国人) 区别也就显而易见了,调用name()方法永远只能得到定义的名称,而toString()方法可以重写,你可以得到你想要得到的自定义名称。其实我们还以把上面重写了toString()方法中的super.toString去掉,修改成: public String toString(){ return people ; } 那么得到的结果如下了: name->Chinese toString->中国人 其实private People(String people)该构造函数可以有多个参数,参数的个数是由自定义的名称的参数而决定的,例如我们可以定义成这样: Chinese("中国人",1),American("美国人",2); private People(String people,int num){ } 以上只是个人理解,由于本人学术浅薄,有理解不到位处望大家指点.也希望以上的回答能够对提问者有点帮助
G. java 枚举 参数传递
这样做是不行的,原因是:Java中的对象实例化都是在堆中,如果是普通的类实例变量,比如在方法1中定义的普通类实例变量,传到了方法2中,由于方法1和方法2中的实例变量对应着堆中的同一个对象实例,所以方法2中修改了对象实例的值,方法1中的值也会跟着变化。但是java中的枚举不是这样子的。比如下面的代码:
publicclassEnumClass{
publicstaticvoidmain(String[]args){
Colorcolor=Color.RED;
convert(color);
System.out.println(color.name());
}
publicstaticvoidconvert(Colorc){
System.out.println(c.name());
c=Color.BLUE;
}
}
enumColor{
RED,BLUE,GREEN;
}
如你问题中表述的,两次输出都是RED。具体原因,我们可以用javap反编译一下这个类。得到下面的代码
Compiledfrom"EnumClass.java"
finalclassorg.concurrency.art.Colorextendsjava.lang.Enum<org.concurrency.art.Color>{
publicstaticfinalorg.concurrency.art.ColorRED;
publicstaticfinalorg.concurrency.art.ColorBLUE;
publicstaticfinalorg.concurrency.art.ColorGREEN;
publicstaticorg.concurrency.art.Color[]values();
publicstaticorg.concurrency.art.ColorvalueOf(java.lang.String);
static{};
}
可以看到枚举其实也是用class实现的。而枚举的值是这个类的static final型的常量。当EnumClass这个类加载后,虚拟机就会在堆区创建这三个实例化变量。这就可以回答为什么改变后无效了。main方法把color变量传递给convert方法的c时,两者是指向堆区中的同一个地址,也就是Color.RED实例的地方,而后,变量c被重新赋值,此时变量c是指向了堆区中的Color.BLUE实例的位置。 这个赋值跟main方法中color变量是没有一点关系的,main中的color变量还是指向的Color.RED实例的地方。 所以covert方法执行完后,main方法中的color变量是没有变的。
如果想要它变化,我感觉有两种方法,一种是covert方法返回一个想要的枚举变量,在main中赋值给color,另一种方法是把这个变量再用一个类封装一下,传入到covert方法中。希望对你有帮助。
H. java反编译工具有哪些
1、 Java反编译插件—Jadclipse
JadClipse是Jad的Eclipse插件,是一款非常实用而且方便地Java反编译插件,我们只需将下载的插件包复制到eclipse的plugins目录下,然后修改window -> Preferences -> Java -> JadClipse 下的Path to decompiler ,如:C:\pin\jadnt158\jad.exe,最后在Windows -> Perference -> General -> Editors -> File Associations中修改“*.class”默认关联的编辑器为“JadClipse Class File Viewer” 即可。
2、 Java反编译工具 —jad
jad是一款使用非常广泛地Java反编译工具,上面这款Jadclipse就是基于jad的反编译插件,JAD 文件包含 MIDlet 套件的标题信息,例如开发应用程序的公司、应用程序名称和大小。
3、 Java 反编译器—JD-GUI
JD-GUI 是一个用 C++ 开发的 Java 反编译工具,由 Pavel Kouznetsov开发,支持Windows、linux和苹果Mac Os三个平台。而且提供了Eclipse平台下的插件JD-Eclipse。JD-GUI不需要安装,直接点击运行,可以反编译jar,class文件。
4、 Java反编译器—jdec
jdec是一个Java反编译器。它能够把出现在一个.class文件中的字节码还原成Java源代码,反编译的结果几乎与原始Java文件相同。它还自带一个利用swing开发的用户操作界面。
5、 uuDeJava
uuDeJava是Java Class文件的反编译工具。反编译的Java源程序被输出到Class的相同目录。内部使用jad.exe。反编译Class文件时,可以直接点击Class文件(关联后),或者选中文件或目录发送到uuDeJava的快捷方式。还可以拖动文件或目录到uuDeJava的主窗口。
6、 Java 反向工程软件—Minjava
Minjava 是一个 Java 反向工程软件,可帮助理解已存在一些 Java 软件的架构和行为。
7、 Java Decompiler
这款反编译器叫 “Java Decompiler”, 由 Pavel Kouznetsov开发,目前最新版本为0.2.5. 它由 C++开发,并且官方可以下载 windows、linux和苹果Mac Os三个平台的可执行程序。
参考资料:http://www.kiwisec.com/news/detail/592e90c09a3e7a3fddc62db7.shtml
I. enum在java中是什么意思
Enum 类型的介绍
枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中。而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常量的定义相似。不过相比较常量类型,枚举类型可以为申明的变量提供更大的取值范围。
举个例子来说明一下,如果希望为彩虹描绘出七种颜色,你可以在 Java 程序中通过常量定义方式来实现。
清单 1. 常量定义
PublicstaticclassRainbowColor{
//红橙黄绿青蓝紫七种颜色的常量定义
publicstaticfinalintRED=0;
publicstaticfinalintORANGE=1;
publicstaticfinalintYELLOW=2;
publicstaticfinalintGREEN=3;
publicstaticfinalintCYAN=4;
publicstaticfinalintBLUE=5;
publicstaticfinalintPURPLE=6;
}
使用的时候,你可以在程序中直接引用这些常量。但是,这种方式还是存在着一些问题。
类型不安全
由于颜色常量的对应值是整数形,所以程序执行过程中很有可能给颜色变量传入一个任意的整数值,导致出现错误。
没有命名空间
由于颜色常量只是类的属性,当你使用的时候不得不通过类来访问。
一致性差
因为整形枚举属于编译期常量,所以编译过程完成后,所有客户端和服务器端引用的地方,会直接将整数值写入。这样,当你修改旧的枚举整数值后或者增加新的枚举值后,所有引用地方代码都需要重新编译,否则运行时刻就会出现错误。
类型无指意性
由于颜色枚举值仅仅是一些无任何含义的整数值,如果在运行期调试时候,你就会发现日志中有很多魔术数字,但除了程序员本身,其他人很难明白其奥秘。
如何定义 Enum 类型
为了改进 Java 语言在这方面的不足弥补缺陷,5.0 版本 SDK 发布时候,在语言层面上增加了枚举类型。枚举类型的定义也非常的简单,用 enum 关键字加上名称和大括号包含起来的枚举值体即可,例如上面提到的彩虹颜色就可以用新的 enum 方式来重新定义:
enumRainbowColor{RED,ORANGE,YELLOW,GREEN,CYAN,BLUE,PURPLE}
从上面的定义形式来看,似乎 Java 中的枚举类型很简单,但实际上 Java 语言规范赋予枚举类型的功能非常的强大,它不仅是简单地将整形数值转换成对象,而是将枚举类型定义转变成一个完整功能的类定义。这种类型定义的扩展允许开发者给枚举类型增加任何方法和属性,也可以实现任意的接口。另外,Java 平台也为 Enum 类型提供了高质量的实现,比如默认实现 Comparable 和 Serializable 接口,让开发者一般情况下不用关心这些细节。
回到本文的主题上来,引入枚举类型到底能够给我们开发带来什么样好处呢?一个最直接的益处就是扩大 switch 语句使用范围。5.0 之前,Java 中 switch 的值只能够是简单类型,比如 int、byte、short、char, 有了枚举类型之后,就可以使用对象了。这样一来,程序的控制选择就变得更加的方便,看下面的例子:
清单 2. 定义 Enum 类型
//定义一周七天的枚举类型
publicenumWeekDayEnum{Mon,Tue,Wed,Thu,Fri,Sat,Sun}
//读取当天的信息
WeekDayEnumtoday=readToday();
//根据日期来选择进行活动
switch(today){
Mon:dosomething;break;
Tue:dosomething;break;
Wed:dosomething;break;
Thu:dosomething;break;
Fri:dosomething;break;
Sat:playsportsgame;break;
Sun:havearest;break;
}
对于这些枚举的日期,JVM 都会在运行期构造成出一个简单的对象实例一一对应。这些对象都有唯一的 identity,类似整形数值一样,switch 语句就根据此来进行执行跳转。
如何定制 Enum 类型
除了以上这种最常见的枚举定义形式外,如果需要给枚举类型增加一些复杂功能,也可以通过类似 class 的定义来给枚举进行定制。比如要给 enum 类型增加属性,可以像下面这样定义:
清单 3. 定制枚举类型
//定义RSS(ReallySimpleSyndication)种子的枚举类型
publicenumNewsRSSFeedEnum{
//雅虎头条新闻RSS种子
YAHOO_TOP_STORIES("http://rss.news.yahoo.com/rss/topstories"),
//CBS头条新闻RSS种子
CBS_TOP_STORIES("http://feeds.cbsnews.com/CBSNewsMain?format=xml"),
//洛杉矶时报头条新闻RSS种子
LATIMES_TOP_STORIES("http://feeds.latimes.com/latimes/news?format=xml");
//枚举对象的RSS地址的属性
privateStringrss_url;
//枚举对象构造函数
privateNewsRSSFeedEnum(Stringrss){
this.rss_url=rss;
}
//枚举对象获取RSS地址的方法
publicStringgetRssURL(){
returnthis.rss_url;
}
}
上面头条新闻的枚举类型增加了一个 RSS 地址的属性 , 记录头条新闻的访问地址。同时,需要外部传入 RSS 访问地址的值,因而需要定义一个构造函数来初始化此属性。另外,还需要向外提供方法来读取 RSS 地址。
如何避免错误使用 Enum
不过在使用 Enum 时候有几个地方需要注意:
enum 类型不支持 public 和 protected 修饰符的构造方法,因此构造函数一定要是 private 或 friendly 的。也正因为如此,所以枚举对象是无法在程序中通过直接调用其构造方法来初始化的。
定义 enum 类型时候,如果是简单类型,那么最后一个枚举值后不用跟任何一个符号;但如果有定制方法,那么最后一个枚举值与后面代码要用分号';'隔开,不能用逗号或空格。
由于 enum 类型的值实际上是通过运行期构造出对象来表示的,所以在 cluster 环境下,每个虚拟机都会构造出一个同义的枚举对象。因而在做比较操作时候就需要注意,如果直接通过使用等号 ( ‘ == ’ ) 操作符,这些看似一样的枚举值一定不相等,因为这不是同一个对象实例。
看下面的这个例子:
清单 4. 避免错误使用 Enum 示例
//定义一个一周七天的枚举类型
packageexample.enumeration.codes;
publicenumWeekDayEnum{
Mon(1),Tue(2),Wed(3),Thu(4),Fri(5),Sat(6),Sun(7);
privateintindex;
WeekDayEnum(intidx){
this.index=idx;
}
publicintgetIndex(){
returnindex;
}
}
//客户端程序,将一个枚举值通过网络传递给服务器端
packageexample.enumeration.codes;
importjava.io.IOException;
importjava.io.ObjectOutputStream;
importjava.io.OutputStream;
importjava.net.InetSocketAddress;
importjava.net.Socket;
importjava.net.UnknownHostException;
publicclassEnumerationClient{
publicstaticvoidmain(String...args)throwsUnknownHostException,IOException{
Socketsocket=newSocket();
//建立到服务器端的连接
socket.connect(newInetSocketAddress("127.0.0.1",8999));
//从连接中得到输出流
OutputStreamos=socket.getOutputStream();
ObjectOutputStreamoos=newObjectOutputStream(os);
//将星期五这个枚举值传递给服务器端
oos.writeObject(WeekDayEnum.Fri);
oos.close();
os.close();
socket.close();
}
}
//服务器端程序,将从客户端收到的枚举值应用到逻辑处理中
packageexample.enumeration.codes;
importjava.io.*;
importjava.net.ServerSocket;
importjava.net.Socket;
publicclassEnumerationServer{
publicstaticvoidmain(String...args)throwsIOException,ClassNotFoundException{
ServerSocketserver=newServerSocket(8999);
//建立服务器端的网络连接侦听
Socketsocket=server.accept();
//从连接中获取输入流
InputStreamis=socket.getInputStream();
ObjectInputStreamois=newObjectInputStream(is);
//读出客户端传递来的枚举值
WeekDayEnumday=(WeekDayEnum)ois.readObject();
//用值比较方式来对比枚举对象
if(day==WeekDayEnum.Fri){
System.out.println("'s");
}elseif(day.equals(WeekDayEnum.Fri)){
System.out.println("'s");
}else{
System.out.println("'s");
}
//用switch方式来比较枚举对象
switch(day){
caseMon:
System.out.println("DoMondaywork");
break;
caseTue:
System.out.println("DoTuesdaywork");
break;
caseWed:
System.out.println("DoWednesdaywork");
break;
caseThu:
System.out.println("DoThursdaywork");
break;
caseFri:
System.out.println("DoFridaywork");
break;
caseSat:
System.out.println("DoSaturdaywork");
break;
caseSun:
System.out.println("DoSundaywork");
break;
default:
System.out.println("Idon'tknowwhichisday");
break;
}
ois.close();
is.close();
socket.close();
}
}
打印结果如下:
client Friday enum value is same as server's
Do Friday work
通过程序执行结果,我们能够发现在分布式条件下客户端和服务端的虚拟机上都生成了一个枚举对象,即使看起来一样的 Fri 枚举值,如果使用等号‘ == ’进行比较的话会出现不等的情况。而 switch 语句则是通过 equal 方法来比较枚举对象的值,因此当你的枚举对象较复杂时候,你就需要小心 override 与比较相关的方法,防止出现值比较方面的错误。
Enum 相关工具类
JDK5.0 中在增加 Enum 类的同时,也增加了两个工具类 EnumSet 和 EnumMap,这两个类都放在 java.util 包中。EnumSet 是一个针对枚举类型的高性能的 Set 接口实现。EnumSet 中装入的所有枚举对象都必须是同一种类型,在其内部,是通过 bit-vector 来实现,也就是通过一个 long 型数。EnumSet 支持在枚举类型的所有值的某个范围中进行迭代。回到上面日期枚举的例子上:
enumWeekDayEnum{Mon,Tue,Wed,Thu,Fri,Sat,Sun}
你能够在每周七天日期中进行迭代,EnumSet 类提供一个静态方法 range 让迭代很容易完成:
for(WeekDayEnumday:EnumSet.range(WeekDayEnum.Mon,WeekDayEnum.Fri)){
System.out.println(day);
}
打印结果如下:
Mon
Tue
Wed
Thu
Fri
EnumSet 还提供了很多个类型安全的获取子集的 of 方法,使你很容易取得子集:
EnumSet<WeekDayEnum>subset=EnumSet.of(WeekDayEnum.Mon,WeekDayEnum.Wed);
for(WeekDayEnumday:subset){
System.out.println(day);
}
打印结果如下:
Mon
Wed
与 EnumSet 类似,EnumMap 也是一个高性能的 Map 接口实现,用来管理使用枚举类型作为 keys 的映射表,内部是通过数组方式来实现。EnumMap 将丰富的和安全的 Map 接口与数组快速访问结合到一起,如果你希望要将一个枚举类型映射到一个值,你应该使用 EnumMap。看下面的例子:
清单 5. EnumMap 示例
//定义一个EnumMap对象,映射表主键是日期枚举类型,值是颜色枚举类型
privatestaticMap<WeekDayEnum,RainbowColor>schema=
newEnumMap<WeekDayEnum,RainbowColor>(WeekDayEnum.class);
static{
//将一周的每一天与彩虹的某一种色彩映射起来
for(inti=0;i<WeekDayEnum.values().length;i++){
schema.put(WeekDayEnum.values()[i],RainbowColor.values()[i]);
}
}
System.out.println("Whatistheluckycolortoday?");
System.out.println("It's"+schema.get(WeekDayEnum.Sat));
当你询问周六的幸运色彩时候,会得到蓝色:
清单 6. 运行结果
What is the lucky color today?
It's BLUE
结束语
Enum 类型提出给 JAVA 编程带了了极大的便利,让程序的控制更加的容易,也不容易出现错误。所以在遇到需要控制程序流程时候,可以多想想是否可以利用 enum 来实现。
J. java编译时出现错误: 需要class, interface或enum
这个错误还不是代码的问题,而是文件编码的问题。
楼主估计是用了一个非记事本的编辑器吧?这个文件因编码的问题,在java.util.*;
这条语句的开头也就是i前面隐藏了一个字符,就像是\n回车这种字符,你是看不到的。解决办法就是新建一个文本文件,用记事本打开,把你的这些代码复制进去,重命名为cat.java
就可以了。