1. 程式人生 > >反編譯那些事兒(二)—列舉的反編譯

反編譯那些事兒(二)—列舉的反編譯

說明:下面的反編譯結果使用“http://download.csdn.net/detail/wangshuxuncom/6841823”處的反編譯工具反編譯的。

一、不含有抽象的方法

原始碼如下:

import java.util.Arrays;
import java.util.List;

public enum Weather {

	Sunny(1, "晴天"), Rainy(2, "雨天"), Cloudy(3, "多雲");
	private int value;
	private String label;

	private Weather(int value, String label) {
		this.value = value;
		this.label = label;
	}

	public int getValue() {
		return value;
	}

	public String getLabel() {
		return label;
	}

	public static Weather parse(int value) {
		Weather result = Weather.Sunny;
		switch (value) {
		case 1:
			result = Weather.Sunny;
			break;
		case 2:
			result = Weather.Rainy;
			break;
		case 3:
			result = Weather.Cloudy;
			break;
		}
		return result;
	}

	public static List<Weather> getEnumValues() {
		return Arrays.asList(values());
	}

	public static void main(String[] args) {
		System.out.println(Weather.Sunny.getValue() + ":" + Weather.Sunny.getLabel());
		Weather weather = Weather.Cloudy;
		System.out.println(weather.getValue() + ":" + weather.getLabel());
		List<Weather> list = getEnumValues();
		for (Weather sw : list) {
			System.out.println(sw.value + "--" + sw.label);
		}
	}
}

反編譯生成的class檔案後的程式碼如下:

/*import java.io.PrintStream;*/
import java.util.*;

public final class Weather extends Enum{
	
	private Weather(/*String s, int i,*/ int value, String label){
		/*super(s, i);*/
		this.value = value;
		this.label = label;
	}
	
	public int getValue(){
		return value;
	}
	
	public String getLabel(){
		return label;
	}
	
	public static Weather parse(int value){
		Weather result = Sunny;
		switch(value){
			case 1: /*// '\001'*/
				result = Sunny;
				break;
			case 2: /*// '\002'*/
				result = Rainy;
				break;
			case 3: /*// '\003'*/
				result = Cloudy;
				break;
		}
		return result;
	}
	
	public static List getEnumValues(){
		return Arrays.asList(values());
	}
	
	public static void main(String args[]){
		System.out.println((new StringBuilder(String.valueOf(Sunny.getValue()))).append(":").append(Sunny.getLabel()).toString());
		Weather weather = Cloudy;
		System.out.println((new StringBuilder(String.valueOf(weather.getValue()))).append(":").append(weather.getLabel()).toString());
		List list = getEnumValues();
		Weather sw;
		for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println((new StringBuilder(String.valueOf(sw.value))).append("--").append(sw.label).toString()))
			sw = (Weather)iterator.next();
	}
	
	/*public static Weather[] values(){
		Weather aweather[];
		int i;
		Weather aweather1[];
		System.arraycopy(aweather = ENUM$VALUES, 0, aweather1 = new Weather[i = aweather.length], 0, i);
		return aweather1;
	}*/
	
	/*public static Weather valueOf(String s){
		return (Weather)Enum.valueOf(Weather, s);
	}*/
	
	/*public static final Weather*/ Sunny;
	/*public static final Weather*/ Rainy;
	/*public static final Weather*/ Cloudy;
	private int value;
	private String label;
	/*private static final Weather ENUM$VALUES[];*/
	static {
		Sunny = new Weather(/*"Sunny", 0,*/ 1, "\u6674\u5929");
		Rainy = new Weather(/*"Rainy", 1,*/ 2, "\u96E8\u5929");
		Cloudy = new Weather(/*"Cloudy", 2,*/ 3, "\u591A\u4E91");
		/*ENUM$VALUES = (new Weather[] {
			Sunny, Rainy, Cloudy
		});*/
	}
}
注意:所有/**/中間的東西都是多餘的(/**/是人為新增的)

如何將反編譯程式碼還原:

①、去掉被/**/掉的程式碼,去掉後代碼如下:

import java.util.*;

public final class Weather extends Enum{
    private Weather(int value, String label){
    	this.value = value;
    	this.label = label;
    }

    public int getValue(){
    	return value;
    }

    public String getLabel(){
    	return label;
    }

    public static Weather parse(int value){
         Weather result = Sunny;
         switch(value){
         	case 1:
         		result = Sunny;
         			break;
         	case 2:
         		result = Rainy;
         		break;
         	case 3:
         		result = Cloudy;
         		break;
        }
        return result;
    }

    public static List getEnumValues(){
    	return Arrays.asList(values());
    }

    public static void main(String args[]){
    	System.out.println((new StringBuilder(String.valueOf(Sunny.getValue()))).append(":").append(Sunny.getLabel()).toString());
        Weather weather = Cloudy;
        System.out.println((new StringBuilder(String.valueOf(weather.getValue()))).append(":").append(weather.getLabel()).toString());
        List list = getEnumValues();
        Weather sw;
        for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println((new StringBuilder(String.valueOf(sw.value))).append("--").append(sw.label).toString()))
        sw = (Weather)iterator.next();
	}

    Sunny;
    Rainy;
    Cloudy;
    private int value;
    private String label;
    static {
    	Sunny = new Weather(1, "\u6674\u5929");
    	Rainy = new Weather(2, "\u96E8\u5929");
    	Cloudy = new Weather(3, "\u591A\u4E91");
    }
}

②、在上一步的基礎上對照非反編譯中的java原始碼可以還原大概,呵呵呵,可能你會說“狗屁,我要是知道原始碼了,還反編譯幹什麼”,呵呵呵,別急,如果你能把上面的這個弄明白了,你就會反編譯沒有原始碼參考的列舉類了。

③、呵呵呵,本來到此就可以了事了,可是還是禁不住提幾個地方:注意反編譯前java檔案和反編譯後生成的java檔案在引類的區別;注意反編譯class檔案後的泛型沒有了;從反編譯的結果中可以得出這樣的結論:實際上列舉型別就是以Java類來實現的,沒有什麼新的特點,只不過java編譯器幫我們做了語法的解析和編譯。

二、含有抽象的方法

原始碼如下:

import java.util.Arrays;
import java.util.List;

public enum Weather {
	
	Sunny(1, "晴天") {
		@Override
		public String test() {
			return "今天陽光明媚!!!\n";
		}
	},
	Rainy(2, "雨天") {
		@Override
		public String test() {
			return "出門別忘帶把雨傘哦!!!\n";
		}
	},
	Cloudy(3, "多雲") {
		@Override
		public String test() {
			return "別出去登高望遠了,你看不遠的,呵呵呵!!!\n";
		}
	};

	private int value;
	private String label;

	private Weather(int value, String label) {
		this.value = value;
		this.label = label;
	}

	public int getValue() {
		return value;
	}

	public String getLabel() {
		return label;
	}

	public abstract String test();

	public static Weather parse(int value) {
		Weather result = Weather.Sunny;
		switch (value) {
		case 1:
			result = Weather.Sunny;
			break;
		case 2:
			result = Weather.Rainy;
			break;
		case 3:
			result = Weather.Cloudy;
			break;
		}
		return result;
	}

	public static List<Weather> getEnumValues() {
		return Arrays.asList(values());
	}

	public static void main(String[] args) {
		System.out.println(Weather.Sunny.getValue() + ":" + Weather.Sunny.getLabel());
		Weather weather = Weather.Cloudy;
		System.out.println(weather.getValue() + ":" + weather.getLabel() + "\n\n");
		List<Weather> list = getEnumValues();
		for (Weather sw : list) {
			System.out.println(sw.value + "--" + sw.label + "--" + sw.test());
		}
	}
}

反編譯生成的class檔案後的程式碼如下:

import java.io.PrintStream;
import java.util.*;

public abstract class Weather extends Enum {

	private Weather(String s, int i, int value, String label) {
		super(s, i);
		this.value = value;
		this.label = label;
	}

	public int getValue() {
		return value;
	}

	public String getLabel() {
		return label;
	}

	public abstract String test();

	public static Weather parse(int value) {
		Weather result = Sunny;
		switch (value) {
		case 1: // '\001'
			result = Sunny;
			break;
		case 2: // '\002'
			result = Rainy;
			break;
		case 3: // '\003'
			result = Cloudy;
			break;
		}
		return result;
	}

	public static List getEnumValues() {
		return Arrays.asList(values());
	}

	public static void main(String args[]) {
		System.out.println((new StringBuilder(String.valueOf(Sunny.getValue()))).append(":").append(Sunny.getLabel()).toString());
		Weather weather = Cloudy;
		System.out.println((new StringBuilder(String.valueOf(weather.getValue()))).append(":").append(weather.getLabel()).append("\n\n").toString());
		List list = getEnumValues();
		Weather sw;
		for (Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println((new StringBuilder(String.valueOf(sw.value))).append("--").append(sw.label).append("--").append(sw.test()).toString()))
			sw = (Weather) iterator.next();
	}

	public static Weather[] values() {
		Weather aweather[];
		int i;
		Weather aweather1[];
		System.arraycopy(aweather = ENUM$VALUES, 0, aweather1 = new Weather[i = aweather.length], 0, i);
		return aweather1;
	}

	public static Weather valueOf(String s) {
		return (Weather) Enum.valueOf(Weather, s);
	}

	Weather(String s, int i, int j, String s1, Weather weather) {
		this(s, i, j, s1);
	}

	public static final Weather Sunny;
	public static final Weather Rainy;
	public static final Weather Cloudy;
	private int value;
	private String label;
	private static final Weather ENUM$VALUES[];

	static {
		Sunny = new Weather("Sunny", 0, 1, "\u6674\u5929") {
			public String test() {
				return "\u4ECA\u5929\u9633\u5149\u660E\u5A9A\uFF01\uFF01\uFF01\n";
			}
		};
		Rainy = new Weather("Rainy", 1, 2, "\u96E8\u5929") {
			public String test() {
				return "\u51FA\u95E8\u522B\u5FD8\u5E26\u628A\u96E8\u4F1E\u54E6\uFF01\uFF01\uFF01\n";
			}
		};
		Cloudy = new Weather("Cloudy", 2, 3, "\u591A\u4E91") {
			public String test() {
				return "\u522B\u51FA\u53BB\u767B\u9AD8\u671B\u8FDC\u4E86\uFF0C\u4F60\u770B\u4E0D\u8FDC\u7684\uFF0C\u5475\u5475\u5475\uFF01\uFF01\uFF01\n";
			}
		};
		ENUM$VALUES = (new Weather[] { Sunny, Rainy, Cloudy });
	}
}

總結:對比原始碼和編譯程式碼,找出他們的區別並不難,做到這一點就可以反編譯含有抽象方法的列舉class檔案,呵呵呵呵,將“不含抽象方法”的class反編譯檔案和“含有抽象方法”的class反編譯檔案,你應該還有一個很大的收穫,呵呵呵,看著:

“不含抽象方法”的class反編譯檔案:public final class Weather extends Enum

“含有抽象方法”的class反編譯檔案:public abstractclass Weather extends Enum