Calling method of innerclass using reflection android java getting InstantiationException - java

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.

Related

Is constructor the only way to create the object of a class in JAVA?

If a constructor is the only way to create the object of a class then how
String name = "Java";
is able to create an object of String class even without using constructor.
No. Constructor is not the only way.
There are at least two more ways:
Clone the object
Serialize and then deserialize object.
Though in case with your example - neither of these is used.
In this case Java uses string pool
There is another way of creating objects via
Class.forName("fully.qualified.class.name.here").newInstance()
Class.forName("fully.qualified.class.name.here").getConstuctor().newInstance()
but they call constructor under the hood.
Other ways to create objects are cloning via clone() method and deserialization.
I suppose in a loop-hole type of way you could use the class object too:
// Get the class object using an object you already have
Class<?> clazz = object.getClass();
// or get class object using the type
Class<?> clazz = Object.class;
// Get the constructor object (give arguments
// of Class objects of types if the constructor takes arguments)
Constructor<?> constructor = clazz.getConstructor();
// then invoke it (and pass arguments if need be)
Object o = constructor.newInstance();
I mean you still use the constructor so it probably doesn't really count. But hey, its there!
Java doc link for Class object
YES, each time a new object is created, at least one constructor will be invoked.
Look at this tutorial, this will explain all with objects, classes and constructors.

Is it okay to not use a constructor in a class?

I have a class, which has some private static final fields (unsure if it is correct to call these constants), and one other instance variable set just private, which is direct copy of one of the private static final fields.
Every time the object is created from other classes, I want it to have the same variables, as they are assigned in the class, and without creating a constructor, Java allows me access all of the methods with the correct returns as I would expect.
Is it okay to not create a constructor in this case?
There are at least two answers to your question:
It's fine not to include a constructor in your class. The Java compiler will add a default zero-parameters constructor for you.
It sounds like you shouldn't be constructing instances of your class in the first place. :-)
You've said
Every time the object is created from other classes, I want it to have the same variables, as they are assigned in the class, and without creating a constructor, Java allows me access all of the methods with the correct returns as I would expect.
It sounds like you have roughly:
class TheClass {
public final SomeType variable = /*...*/;
// ...
}
...and you're doing this:
TheClass instance = new TheClass();
doSomethingWith(instance.variable);
There's no reason to create an instance there, just use the class name directly:
doSomethingWith(TheClass.variable);
Java is somewhat interesting in that it allows you to access static members via instance references (instance.variable), but the normal way to access them is through the class (TheClass.variable).
Also, if your static members aren't final, you can get some very confusing-seeming behavior:
TheClass a = new TheClass();
a.variable = 1;
TheClass b = new TheClass();
b.variable = 2;
System.out.println(a.variable); // 2?!?!?!
So in general, best to avoid accessing static members via instance references.
Alternately, make the class a singleton with instance (non-static) members instead.

Scala implicit class parameter

I have a class with an implicit parameter defined as:
class Test(implicit one: String)
And I want to instantiate that object like so:
val grr = new Test("aha")
I get the following exception.
error: too many arguments for constructor Test: ()(implicit one: String)Test
val grr = new Test("aha")
But if I call it like so
val grr = new Test()("haha")
grr: Test = Test#3bd40a57
I get a Test object.
Why does Scala instantiate of implicit methods require you to call the object with blank parameters in this instance? Why is there an implicit blank parameter list presented for such object instances?
First, Test is not an implicit class. See this for a discussion of implicit classes.
Instead, Test is a class that has no explicit constructor arguments but one implicit String argument. This means the only way you can instantiate Test is to either provide the implicit argument explicitly as you did, which is awkward and defeats the purpose, or to provide one and only one String in implicit scope at instantiation time and have the compiler "pick it up."
In other words, if you have something like this in scope:
implicit val s: String = "haha"
Then all you will have to do to instantiate Test is this:
val grr = new Test
And if you don't have one in scope, the compiler will let you know it. That's a good thing.
The main thing though is to make sure you get the distinction between implicit parameters and implicit classes.
The implicit blank parameter list is there just for constructors, not all methods. I think this is probably because the parser needs to distinguish between a reference to the type Test (or the companion object) and a reference to the constructor. If it allowed a constructor with no arguments, then Test by itself would be ambiguous.
Normally in scala when you refer to an "implicit class" you do it like this:
object Container {
implicit class Test(val one: string)
}
Then you can do:
import Container._
and it will implicitly convert Strings into Test objects.

Does a Java constructor return the Object reference?

I know Java's constructors can't have any type and interestingly it cannot even be void. A logical explanation for that would be that a constructor returns the initialized object's reference.
MyClass myObject = new MyClass();
The constructor of myClass will now return the object reference after instantiating it and save it in the object variable MyObject and that's why the constructor can't have a return type.
Is that right? Could someone confirm this?
No, actually, the constructors are compiled into the class file like methods having the name <init> and a void return type. You can see these "<init>" invocations in stack traces. The expression new Type() is compiled as an instruction new which just creates the instance of Type and an additional method invokation (invokespecial) to one of the constructors declared in Type.
The verifier will ensure that such a special method is invoked at exactly once on a newly created instance and that it is called before any other use of the object.
It’s just a programming language design decision to let constructors have no return type from the Java language point of view. After all, new Type(…) is an expression that evaluates to the newly created instance of Type and you can’t get a return value from the constructor with that programming language construct. Further, if you add a return type, Java will unconditionally assume that it is a method, even if it has the same name as the class.
That’s simply how it was defined: (It makes parsing the class definition easier)
The SimpleTypeName in the ConstructorDeclarator must be the simple name of the class that contains the constructor declaration, or a compile-time error occurs.
In all other respects, a constructor declaration looks just like a method declaration that has no result (§8.4.5).
I suppose you could say that constructors have a "special syntax" used specifically for returning instances of the desired object. You do not specify the return type in these cases. The new keyword is used together with the constructor method to produce an instance of the class type.
If you'd like to control the return type of an instance generation method, then you should probably be looking at using a type of factory design pattern, wherein a static method creates an instance (using a constructor), and then returns a more explicit type (say for example, the super type, or an interface type).
This pattern is good when you'd like to decide which type to return based on some parameter, but leave the actual type hidden to the consumer of the instance generation method.
A constructor is not a methed. It does not return anything. It is used for initialization purposes, especially useful when those initializations depend on parameters or there is a chance that exceptions will be thrown (though both are optional).
So, unlike a method, it is not inherited and does not have a return type (not even void).
The idea is that you are "constructing" an instance of MyClass by calling the constructor itself. The idea of the constructor is to instantiate and not to return. Having created myObject you can then refer to public methods and variables part of its declaration which will provide you with the required data being returned as an answer to a call. It is important to understand that the constructor does not return anything it simply creates an instance which can then be used to refer to methods and variables (which return data) declared within the instantiated class.

How to instantiate a non-public final class using reflection?

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.

Categories

Resources