久久久久久久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 | 91精品国产91久久综合桃花 | 久久久久电影 | 午夜精品一区 | 综合久久av| 99福利视频导航 | 91精品久久久久久久久中文字幕 | 国产成人99久久亚洲综合精品 | 久久亚洲精品国产精品紫薇 | 成人在线播放网站 | 国色天香综合网 | 欧美亚洲视频在线观看 | 91久久婷婷 | www,黄色,com | 日日淫 | 色www精品视频在线观看 | 亚洲综合视频 | 国产日韩视频 | 天天拍天天操 | 永久www成人看片 | 久久久精品高清 | 日韩在线小视频 | 国产做a爱免费视频 | 超碰在线97国产 | 在线看无码的免费网站 | 欧美一区二区二区 | 99久9 | 91精品久久久久久久久久小网站 | 韩日在线视频 | 亚洲一区二区三区欧美 | 麻豆精品国产91久久久久久 | 国产1区在线 | 中文字幕一区二区三区精彩视频 | 红桃视频一区二区三区免费 | 欧美精品被|