Why does a static nested class cause a second constructor to be added when it is not in the source?

I tried to break the BillPaugh Singleton solution using reflection, but I can do it, but I see two constructors when accessing the BillPaughSingleTon solution. Why is that? In addition, as a result of trial and error, it was discovered that the line inside HelperClass causes this. Why again?

Billpaughclass

package creational.BillPaugh;

public class SingleTonBillPaugh
{
  private SingleTonBillPaugh instance;

  public static SingleTonBillPaugh getInstance()
  {
    return SingleTonHelper.instance;
  }

  private SingleTonBillPaugh()
  {
    System.out.println(Thread.currentThread().getName() + " instance is going to be created");
  }

  static class SingleTonHelper
  {
    private static final SingleTonBillPaugh instance = new SingleTonBillPaugh(); //if we remove this line, multiple constructor will not be there. But this line is needed for singleton. 
  }
}

Break SingleTon using Reflection.

package creational.BillPaugh;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class BreakBillPaughUsingReflection
{
  public static void main(String[] args)
  {

    SingleTonBillPaugh singletonInstance1 = SingleTonBillPaugh.getInstance();
    System.out.println("singletonInstance1 " + singletonInstance1);

    SingleTonBillPaugh singletonInstance2;
    Constructor[] constructors = SingleTonBillPaugh.class.getDeclaredConstructors();

    for (Constructor construct : constructors)
    {
      construct.setAccessible(true);
      try
      {
        singletonInstance2 = (SingleTonBillPaugh) construct.newInstance();
        System.out.println("singletonInstance2 " + singletonInstance2);
      }
      catch (InstantiationException | IllegalAccessException | IllegalArgumentException
        | InvocationTargetException e)
      {
        e.printStackTrace();
      }
    }// end for

    Constructor[] constructors2 = NormalClass.class.getDeclaredConstructors();

  }
}

Proof of two constructors.

enter image description here

+4
source share
1 answer

Here is my trick:

SingleTonBillPaugh private, SingleTonBillPaugh$SingleTonHelper , SingleTonBillPaugh$SingleTonHelper, . , : .

, , SingleTonBillPaugh$1? ( SingleTonBillPaugh, SingleTonBillPaugh$1 instance — SingleTonBillPaugh SingleTonBillPaugh$SingleTonHelper).

: , , SingleTonBillPaugh$SingleTonHelper, - . Java , , , .

, SingleTonBillPaugh$1, javap -p -c SingleTonBillPaugh\$1 it, :

class SingleTonBillPaugh$1 {
}

, , , . , , - SingleTonBillPaugh$SingleTonHelper javap -p -c SingleTonBillPaugh\$SingleTonHelper:

class SingleTonBillPaugh$SingleTonHelper {
  private static final SingleTonBillPaugh instance;

  SingleTonBillPaugh$SingleTonHelper();
    Code:
       0: aload_0
       1: invokespecial #2                  // Method java/lang/Object."<init>":()V
       4: return

  static SingleTonBillPaugh access$000();
    Code:
       0: getstatic     #1                  // Field instance:LSingleTonBillPaugh;
       3: areturn

  static {};
    Code:
       0: new           #3                  // class SingleTonBillPaugh
       3: dup
       4: aconst_null
       5: invokespecial #4                  // Method SingleTonBillPaugh."<init>":(LSingleTonBillPaugh$1;)V
       8: putstatic     #1                  // Field instance:LSingleTonBillPaugh;
      11: return
}

, ( ) ( null).

, , — . , String SingleTonHelper, "", SingleTonBillPaugh(String, SingleTonBillPaugh$1).


:

sysout , ( ), sysout. ? , pvt?

, . , -:

SingleTonBillPaugh.java:

public class SingleTonBillPaugh
{
    public static SingleTonBillPaugh getInstance()
    {
        return SingleTonHelper.instance;
    }

    private SingleTonBillPaugh()
    {
        System.out.println(Thread.currentThread().getName() + " instance is going to be created");
    }

    static class SingleTonHelper
    {
        private static final SingleTonBillPaugh instance = new SingleTonBillPaugh();
    }
}

, javap -p -c SingleTonBillPaugh, :

public class SingleTonBillPaugh {
  public static SingleTonBillPaugh getInstance();
    Code:
       0: invokestatic  #2                  // Method SingleTonBillPaugh$SingleTonHelper.access$000:()LSingleTonBillPaugh;
       3: areturn

  private SingleTonBillPaugh();
    Code:
       0: aload_0
       1: invokespecial #3                  // Method java/lang/Object."<init>":()V
       4: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: new           #5                  // class java/lang/StringBuilder
      10: dup
      11: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
      14: invokestatic  #7                  // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
      17: invokevirtual #8                  // Method java/lang/Thread.getName:()Ljava/lang/String;
      20: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      23: ldc           #10                 // String  instance is going to be created
      25: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      34: return

  SingleTonBillPaugh(SingleTonBillPaugh$1);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method "<init>":()V
       4: return
}

, SingleTonBillPaugh(SingleTonBillPaugh$1), , :

SingleTonBillPaugh(SingleTonBillPaugh$1 unused) {
    this();
}
+5

Source: https://habr.com/ru/post/1570266/


All Articles