久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

匿名類混淆的動態構建

Dynamic construction of anonymous class confusion(匿名類混淆的動態構建)
本文介紹了匿名類混淆的動態構建的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

限時送ChatGPT賬號..

我正在嘗試使用反射創建匿名類的實例.但我偶爾會在實例化過程中看到奇怪的行為.

I'm trying to make instances of anonymous classes using reflection. But ocassionally I've seen strange behaviour during instantination.

請看這些相似的代碼片段

Please, look at these similar fragments of code

public class HideAndSeek {

    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws IllegalAccessException, InstantiationException{

        final String finalString = "I'm final :)";

        Object object2 = new Object(){

            {
                System.out.println("Instance initializing block");
                System.out.println(finalString);
            }           

            private void hiddenMethod() {
                System.out.println("Use reflection to find me :)");
            }
        };

        Object tmp = object2.getClass().newInstance();
    }

}

這段代碼運行良好,預期的輸出

This code works well, and the output expected

Instance initializing block
I'm final :)
Instance initializing block
I'm final :)

在此之后,我決定以簡單的方式更改代碼(只是添加了 java.util.Calendar)

After this I've decided to change code in simple way (just added java.util.Calendar)

import java.util.Calendar;

    public class HideAndSeek {

        @SuppressWarnings("unchecked")
        public static void main(String[] args) throws IllegalAccessException, InstantiationException{

            final String finalString = "I'm final :)";

            final Calendar calendar = Calendar.getInstance();
            System.out.println(calendar.getTime().toString()); //works well

            Object object2 = new Object(){

                {
                    System.out.println("Instance initializing block");
                    System.out.println(finalString);

                    //simply added this line
                    System.out.println(calendar.getTime().toString());
                }           

                private void hiddenMethod() {
                    System.out.println("Use reflection to find me :)");
                }
            };

            Object tmp = object2.getClass().newInstance();
        }

    }

這是我得到的輸出:

Wed Aug 17 02:08:47 EEST 2011
Instance initializing block
I'm final :)
Wed Aug 17 02:08:47 EEST 2011
Exception in thread "main" java.lang.InstantiationException: HideAndSeek$1
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at HideAndSeek.main(HideAndSeek.java:29)

如您所見 - 尚未創建新實例.

As you may see - new instance hasn't been created.

誰能解釋一下,這些變化的原因?

Could anybody explain me, the reason of such changes?

謝謝

推薦答案

這是一個非常簡單的問題,但答案卻非常復雜.請耐心等待我試圖解釋它.

This is a very simple question with a very complex answer. Please bear with me as I try to explain it.

查看 Class 中引發異常的源代碼(我不確定為什么您的堆棧跟蹤沒有給出 Class 中的行號):

Looking at the source code where the exception is raised in Class (I'm not sure why your stack trace doesn't give the line numbers in Class):

try
{
  Class[] empty = {};
  final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
  // removed some code that was not relevant
}
catch (NoSuchMethodException e)
{
  throw new InstantiationException(getName());
}

您看到 NoSuchMethodException 被重新拋出為 InstantiationException.這意味著 object2 的類類型沒有無參數構造函數.

you see that NoSuchMethodException is being rethrown as InstantiationException. This means there is not a no-arg constructor for the class type of object2.

首先,object2是什么類型?用代碼

First, what type is object2? With the code

System.out.println("object2 class: " + object2.getClass());

我們看到了

object2 類:class junk.NewMain$1

object2 class: class junk.NewMain$1

這是正確的(我在包垃圾中運行示例代碼,類 NewMain).

which is correct (I run sample code in package junk, class NewMain).

那么junk.NewMain$1的構造函數是什么?

What then are the constructors of junk.NewMain$1?

Class obj2Class = object2.getClass();
try
{
  Constructor[] ctors = obj2Class.getDeclaredConstructors();
  for (Constructor cc : ctors)
  {
    System.out.println("my ctor is " + cc.toString());
  }
}
catch (Exception ex)
{
  ex.printStackTrace();
}

這給了我們

我的 ctor 是 junk.NewMain$1(java.util.Calendar)

my ctor is junk.NewMain$1(java.util.Calendar)

因此,您的匿名類正在尋找要傳入的 Calendar.這將適用于您:

So your anonymous class is looking for a Calendar to be passed in. This will then work for you:

Object newObj = ctors[0].newInstance(Calendar.getInstance());

如果你有這樣的事情:

final String finalString = "I'm final :)";
final Integer finalInteger = new Integer(30);
final Calendar calendar = Calendar.getInstance();
Object object2 = new Object()
{
  {
    System.out.println("Instance initializing block");
    System.out.println(finalString);
    System.out.println("My integer is " + finalInteger);
    System.out.println(calendar.getTime().toString());
  }
  private void hiddenMethod()
  {
    System.out.println("Use reflection to find me :)");
  }
};

那么我對 newInstance 的調用將不起作用,因為 ctor 中沒有足夠的參數,因為現在它想要:

then my call to newInstance won't work because there are not enough arguments in the ctor, because now it wants:

我的 ctor 是 junk.NewMain$1(java.lang.Integer,java.util.Calendar)

my ctor is junk.NewMain$1(java.lang.Integer,java.util.Calendar)

如果我用

Object newObj = ctors[0].newInstance(new Integer(25), Calendar.getInstance());

使用調試器查看內部顯示 finalInteger 是 25,而不是最終值 30.

a peek inside using the debugger shows that finalInteger is 25 and not the final value 30.

事情有點復雜,因為您是在靜態上下文中執行上述所有操作.如果您將上面的所有代碼移到像這樣的非靜態方法中(請記住,我的類是 junk.NewMain):

Things are slightly complicated because you're doing all of the above in a static context. If you take all your code above and move it into a non-static method like so (remember, my class is junk.NewMain):

public static void main(String[] args)
{
  NewMain nm = new NewMain();
  nm.doIt();
}

public void doIt()
{
  final String finalString = "I'm final :)";
  // etc etc
}

你會發現你的內部類的 ctor 現在是(刪除我添加的 Integer 引用):

you'll find the ctor for your inner class is now (removing my added Integer reference):

我的 ctor 是 junk.NewMain$1(junk.NewMain, java.util.Calendar)

my ctor is junk.NewMain$1(junk.NewMain, java.util.Calendar)

Java 語言規范,15.9.3 是這樣解釋的:

如果 C 是一個匿名類,并且 C 的直接超類 S 是一個內部類,然后:

If C is an anonymous class, and the direct superclass of C, S, is an inner class, then:

  • 如果 S 是本地類并且 S 出現在靜態上下文中,則參數列表中的參數(如果有)是構造函數,按照它們在表達式中出現的順序.
  • 否則,i 的直接封閉實例相對于S 是構造函數的第一個參數,然后是類實例創建的參數列表中的參數表達式(如果有),按照它們在表達式中出現的順序排列.

為什么匿名構造函數完全接受參數?

Why does the anonymous constructor take arguments at all?

由于您無法為匿名內部類創建構造函數,因此實例初始化程序塊用于此目的(請記住,您只有該匿名內部類的一個實例).VM 不知道內部類,因為編譯器將所有內容作為單獨的類(例如 junk.NewMain$1)分離出來.該類的 ctor 包含實例初始化程序的內容.

Since you can't create a constructor for an anonymous inner class, the instance initializer block serves that purpose (remember, you only have one instance of that anonymous inner class). The VM has no knowledge of the inner class as the compiler separates everything out as individual classes (e.g. junk.NewMain$1). The ctor for that class contains the contents of the instance initializer.

這是由 JLS 15.9.5.1匿名構造函數:

...匿名構造函數對每個實際參數都有一個形參類實例創建表達式的參數,其中 C 是聲明.

...the anonymous constructor has one formal parameter for each actual argument to the class instance creation expression in which C is declared.

您的實例初始化程序具有對 Calendar 對象的引用.除了通過構造函數之外,編譯器如何將運行時值獲取到您的內部類(它只是作為 VM 的一個類而創建)?

Your instance initializer has a reference to a Calendar object. How else is the compiler going to get that runtime value into your inner class (which is created as just a class for the VM) except through the constructor?

最后(耶),最后一個亟待解決的問題的答案.為什么構造函數不需要 String?JLS 最后一點 3.10.5 解釋說:

Finally (yay), the answer to the last burning question. Why doesn't the constructor require a String? The last bit of JLS 3.10.5 explains that:

由常量表達式計算的字符串是在編譯時計算的然后將它們視為文字.

Strings computed by constant expressions are computed at compile time and then treated as if they were literals.

換句話說,您的 String 值在編譯時是已知的,因為它是一個文字,因此它不需要是匿名構造函數的一部分.為了證明這種情況,我們將測試 JLS 3.10.5 中的下一條語句:

In other words, your String value is known at compile time because it's a literal so it does not need to be part of the anonymous constructor. To prove this is the case we'll test the next statement in JLS 3.10.5:

在運行時通過連接計算的字符串是新創建的,并且因此不同.

Strings computed by concatenation at run time are newly created and therefore distinct.

因此更改您的代碼:

String str1 = "I'm";
String str2 = " final!";
final String finalString = str1 + str2

你會發現你的 ctor 現在是(在非靜態上下文中):

and you'll find your ctor is now (in the non-static context):

我的 ctor 是 junk.NewMain$1(junk.NewMain,java.lang.String,java.util.Calendar)

my ctor is junk.NewMain$1(junk.NewMain,java.lang.String,java.util.Calendar)

呸.我希望這是有道理的并且是有幫助的.我學到了很多,這是肯定的!

Phew. I hope this makes sense and was helpful. I learned a lot, that's for sure!

這篇關于匿名類混淆的動態構建的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Parsing an ISO 8601 string local date-time as if in UTC(解析 ISO 8601 字符串本地日期時間,就像在 UTC 中一樣)
How to convert Gregorian string to Gregorian Calendar?(如何將公歷字符串轉換為公歷?)
Java: What/where are the maximum and minimum values of a GregorianCalendar?(Java:GregorianCalendar 的最大值和最小值是什么/在哪里?)
Calendar to Date conversion for dates before 15 Oct 1582. Gregorian to Julian calendar switch(1582 年 10 月 15 日之前日期的日歷到日期轉換.公歷到儒略歷切換)
java Calendar setFirstDayOfWeek not working(java日歷setFirstDayOfWeek不起作用)
Java: getting current Day of the Week value(Java:獲取當前星期幾的值)
主站蜘蛛池模板: 日韩精品一区二区三区在线播放 | 日韩精品一区二区三区四区视频 | 黄网站免费在线看 | 亚洲自拍偷拍视频 | 亚洲成av人影片在线观看 | 中文字幕亚洲一区 | 香蕉av免费 | 国产在线播放av | 久久精品网 | 久久99精品久久久久久秒播九色 | 97精品久久 | 国产成人叼嘿视频在线观看 | 亚洲网址在线观看 | 国产精品网址 | 久草在线免费资源 | 国产目拍亚洲精品99久久精品 | 久久精品av麻豆的观看方式 | 天堂视频中文在线 | 成人在线亚洲 | 日韩一区二区三区在线视频 | 一区在线观看 | 国产91视频一区二区 | 一区二区在线不卡 | 中文字幕成人在线 | 国产乱码精品一区二区三区中文 | 欧美一级免费 | www.youjizz.com日韩| 欧美日韩大片 | 国产精品欧美一区二区 | www.成人.com | 久久久精品视频免费看 | 久久久中文 | 色播视频在线观看 | 日韩精品免费在线观看 | 亚洲中午字幕 | 天堂网色| 欧美精品久久久 | 国产1区在线 | 日韩毛片 | 中文字幕亚洲精品在线观看 | 精品国产乱码久久久久久丨区2区 |