I have a non-public final class that looks like the following:
final class FragmentManagerImpl {
...
}
Note that it is not public and it has no declared constructors.
I would like to instantiate an instance of this class using reflection. However, both of the following code snippets result in IllegalAccessExceptions:
// BUG IllegalAccessException on calling newInstance
final Class c = Class.forName("android.support.v4.app.FragmentManagerImpl");
c.newInstance();
// BUG IllegalAccessException on calling newInstance
final Class c = Class.forName("android.support.v4.app.FragmentManagerImpl");
final Constructor constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
constructor.newInstance();
What is the correct way to instantiate this class from a package that is not android.support.v4.app?
According to JavaDocs, you can call getDeclaredConstructors() method and you'll get all the private constructors as well as the default constructor.
public Constructor[] getDeclaredConstructors()
throws SecurityException
Returns an array of Constructor objects reflecting all the
constructors declared by the class represented by this Class object.
These are public, protected, default (package) access, and private
constructors. The elements in the array returned are not sorted and
are not in any particular order. If the class has a default
constructor, it is included in the returned array. This method returns
an array of length 0 if this Class object represents an interface, a
primitive type, an array class, or void.
See The Java Language Specification, section 8.2.
It doesn't specify how exactly this getDeclaredConstructor(Class... parameterTypes) method, that you are using, will work though.
I'm guessing, but I think that it is complaining about the accessibility of the class not (just) the constructor.
Try calling setAccessible(true) on the Class object as well as the Constructor object.
Hm, it appears to have been user error. Using the constructor method outlined in the question does seem to have worked properly.
Related
This question already has answers here:
What is the actual use of the default constructor in java?
(7 answers)
Closed 4 years ago.
There is something that I don't understand about the real role of the default constructor in java. In the official tutorial about object creation :
Creating Objects
All classes have at least one constructor. If a class does not explicitly declare any, the Java compiler automatically provides a no-argument constructor, called the default constructor. This default constructor calls the class parent's no-argument constructor, or the Object constructor if the class has no other parent. If the parent has no constructor (Object does have one), the compiler will reject the program.
And in the docs about the Default Constructor (§8.8.9)
8.8.9. Default Constructor
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
So even the default constructor of the class Object has an empty body. And I know that the default constructor does NOT initialize fields to their default values, because it's the compiler who does that :
Default Values
It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler.
What I don't understand is, if we didn't declare a constructor, what does the default constructor really do ?
what does the default constructor really do?
It calls super(). As per all your quotations. And does nothing else. JLS #8.8.9:
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
i.e. it does nothing else. For those who believe it initializes instance variables please see JLS #12.5 where the contrary is asserted.
In Java, if you don´t declare any constructor the compiler create a default constructor and this constructor call to super() method, that is parents constructor. And in this process, inits instance variables like no-default constructors.
What I don't understand is, if we didn't declare a constructor, what
does the default constructor really do ?
By default, if no constructor is declared, a class has a default constructor with no args. I think that's why, by default all constructor calls super(). It follows probably the convention over configuration principle.
Whatever you declare a public constructor or you don't declare at all constructor, first instruction of the constructor is super().
That's why if you define in a class MyClass a constructor with args MyClass(String s) without keeping a constructor with no argument, constructor of MyClass subclasses cannot compile while it doesn't precise in their first instruction, the call to an existing parent constructor, in the exemple, it would be super(String ...).
Here an example :
public class MyClassWithNoArg{
public MyClassWithNoArg(){
}
}
MyClassWithNoArg constructor calls super() in this first instruction even if it not specified in the source code.
It is as if it is written in this way :
public class MyClassWithNoArg{
public MyClassWithNoArg(){
super();
}
}
Imagine now another class MyClassWithArg:
public class MyClassWithArg{
public MyClassWithNoArg(String s){
}
}
And MySubclass a subclass of MyClassWithArg
public class MySubclass extends MyClassWithArg{
public MySubclass (String s){
}
public MySubclass (){
}
}
In both cases, it will not compile since as explained previously all constructors call by default the default constructor (super()) of their parent but here the parent,MyClassWithArg, has no constructor with no arg. So, it doesn't compile.
So to solve the problem, you have to call the super constructor which exists.
public class MySubclass extends MyClassWithArg{
public MySubclass (String s){
super(s);
}
public MySubclass (){
super("");
}
}
Now, compilation is OK.
Without constructor no one can create a object of a class. Now if programmer does not add any constructor with a class then java compiler added a constructor with that class before compilation,which is known as default constructor in java.
But if programmer adds any kind of constructor(with argument or without argument) then that becomes user defined constructor and no constructor 'll be added via java compiler.
Now question is what does constructor do.
allocates memory for new object
if user defines any other operation like initialising variable that is done.
I have been programming java professionally for more than ten years. This is one of the weirdest bugs I've ever tried to track down. I have a private member, I initialize it and then it changes to null all by itself.
public class MyObject extends MyParent
{
private SomeOtherClass member = null;
public MyObject()
{
super();
}
public void callbackFromParentInit()
{
member = new SomeOtherClass();
System.out.println("proof member initialized: " + member);
}
public SomeOtherClass getMember()
{
System.out.println("in getMember: " + member);
return member;
}
}
Output:
proof member initialized: SomeOtherClass#2a05ad6d
in getMember: null
If you run this code, obviously it will work properly. In my actual code there are only these three occurrences (five if you count the printlns) in this exact pattern.
Have I come across some bug in the JVM? Unless I'm wrong, the parent class can't interfere with a private member, and no matter what I put between the lines of code I've shown you, I can't change the value of member without using the identifier "member".
This happens because of the order in which member variables are initialized and constructors are called.
You are calling callbackFromParentInit() from the constructor of the superclass MyParent.
When this method is called, it will set member. But after that, the subclass part of the object initialization is performed, and the initializer for member is executed, which sets member to null.
See, for example:
What's wrong with overridable method calls in constructors?
State of Derived class object when Base class constructor calls overridden method in Java
Using abstract init() function in abstract class's constructor
In what order constructors are called and fields are initialized is described in paragraph 12.5 of the Java Language Specification.
Assignment of null to field member happens after executing parent constructor.
The fix is to change:
private SomeOtherClass member = null;
to:
private SomeOtherClass member;
Never, never ever call a non final method from the superclass' constructor.
It's considered bad practice, precisely because it can lead to nasty, hard-to-debug errors like the one you're suffering.
Perform initialization of a class X within X's constructor. Don't rely on java's initialization order for hierarchies. If you can't initialize the class property i.e. because it has dependencies, use either the builder or the factory pattern.
Here, the subclass is resetting the attribute member to null, due to superclass and subclass constructors and initializer block execution order, in which, as already mentioned, you shouldn't rely.
Please refer to this related question for concepts regarding constructors, hierarchies and implicit escaping of the this reference.
I can only think about sticking to a (maybe incomplete) set of rules/principles to avoid this problem and others alike:
Only call private methods from within the constructor
If you like adrenaline and want to call protected methods from within the constructor, do it, but declare these methods as final, so that they cannot be overriden by subclasses
Never create inner classes in the constructor, either anonymous, local, static or non-static
In the constructor, don't pass this directly as an argument to anything
Avoid any transitive combination of the rules above, i.e. don't create an anonymous inner class in a private or protected final method that is invoked from within the constructor
Use the constructor to just construct an instance of the class, and let it only initialize attributes of the class, either with default values or with provided arguments
public class TransparentProxy {
private static ProxyServer _proxyserver = null;
private static TransparentProxy _instance = null;
public TransparentProxy() {
}
public static void main(String args[]) throws Exception {
TransparentProxy.getInstance();
}
I understand everything except the public TransparentProxy() {}. Why is it empty? What is its purpose? Why is it exempt from having a return type?
I have looked it up but can't get an exact answer. Thanks
From the tutorial of the initial part of - Learning the Java Language
A class contains constructors that are invoked to create objects from the class blueprint.
Constructor declarations look like method declarations—except that they use the name of the class
and have no return type.
You don't have to provide any constructors for your class, but you must be careful when doing this.
The compiler automatically provides a no-argument, default constructor for any class without
constructors. This default constructor will call the no-argument constructor of the superclass.
It looks like you've not read through the basics of Java language yet, you should go through them.
This is an empty constructor. It has no return types and named as the class name.
An empty constructor is needed to create a new instance via reflection by your persistence framework. If you don't provide any additional constructors with arguments for the class, you don't need to provide an empty constructor because you get one per default.
public TransparentProxy() {} ---is a Constructor
Java constructors are the methods with the same name as the Class with no return type/value. They are called or invoked when an object of class is created and can't be called explicitly. An object of a class is created using the new keyword. Ex: TransparentProxy proxy = new TransparentProxy();
Three types of Constructors are present.
1. Default Constructor
JVM internally declares a constructor when no constructor in specified. This is to allow a class to create an instance of it. Also, an Interface in Java does not have a constructor and hence no instances/object can be created.
2. Zero argument Constructor
A constructor defined with no arguments is called a Zero argument Constructor. You may use it to initialize variables to some value to begin with. All objects/instances of the class will have the same initial values.
3. Constructor with arguments
Its a constructor defined with arguments which initialize the variables of the class at the time of object creation. Every object/instance created of that class will have different initial values depending on the values passed to the constructor.
A constructor can be overloaded with different type of arguments or the number of arguments.
It cannot be overrided in a sub class.
Read here -- Why do constructors not return values?
I have the following code, and I am getting Instantiation exception when i invoke the newInstnace()
Can you please help
Class cls = Class.forName("com.android.internal.os.BatteryStatsImpl$Uid");
Object obj = cls.newInstance();
Unless the inner class is declared static, you can't create an instance of the inner class without an instance of the outer class for it to belong to. Once you have one of those, then you need to use reflection to get the inner class's constructor. Note this from the documentation for Class.getConstructor:
If this Class object represents an inner class declared in a non-static context, the formal parameter types include the explicit enclosing instance as the first parameter.
Finally, you need to invoke the constructor's newInstance method, passing it the instance of the outer class as the first argument.
With an instance of the enclosing class, you don't actually need reflection:
BatteryStatsImpl stats = . . .;
com.android.internal.os.BatteryStatsImpl.Uid obj = stats.new Uid();
EDIT Per request, here's some sample code (with no error checking):
Class<?> statsClass = Class.forName("com.android.internal.os.BatteryStatsImpl");
Object statsObject = statsClass.newInstance();
Class<?> uidClass = Class.forName("com.android.internal.os.BatteryStatsImpl$Uid");
Constructor<?> ctor = uidClass.getConstructor(statsClass);
Object uidObject = ctor.newInstance(statsObject);
Note, of course, that since all this is part of the Android internals (and not part of the published API) it comes with a standard "use at your own risk" warning: The classes you are using are subject to change (or disappearance) without notice in future versions of Android.
Collections is a public class, then we can call its implicit default constructor. It doesn't have private constructor, which would prevent object creation or force to have static factory method. When I do instantiate as new Collections(), i get error as "Constructor not visible". In short why can't we have instance of java.util.Collections class? Thanks.
From the documentation: "This class consists exclusively of static methods that operate on or return collections."
In other words, Collections is just a collection of methods. An instance of it would not make any sense. It is just like the math functions: You don't have an instance of math, you just use the functions.
It is not an interface as it has concrete methods.
The reason for the "Constructor not visible" message is that the constructor is private (line 73), or at least according to this site . And as others already stated, what would you do with an instance of this class as it only contains static methods
// Suppresses default constructor, ensuring non-instantiability.
private Collections() {
}