Scala implicit class parameter - java

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.

Related

Two observables point to the same reference

I wrote the following example and checked the value of the observerA variable for objects a and b.
Example
class Test {
val observerA = Observer<String>{}
}
Check
val a = Test()
val b = Test()
AppLogger.LOGE("[A]ObserverA: ${a.observerA} [B]ObserverA: ${b.observerA}")
Result
[A]ObserverA: com.test.Test$observerA$1#e3d8a1b
[B]ObserverA: com.test.Test$observerA$1#e3d8a1b
My guess is that a.observerA and a.observerA should be different, but they refer to the same object.
When I wrote observerA as below, I saw that different objects were created. I do not know why this difference appears.
val observerA = object : Observer<String>{
override fun onChanged(t: String?) {
}
}
When you use this syntax, you're defining a lambda with an empty body:
Observer<String>{}
This lambda will be compiled down to an anonymous class. If the lambda doesn't capture any variables, as an optimization step, there'll only be one instance of it (since you can't tell the difference in behaviour anyway).
As you've discovered already, you can force the compiler to create new instances of this Observer by using the full object expression syntax, which guarantees a new instance every time.
Source for the statements above, from the Kotlin in Action book:
As of Kotlin 1.0, every lambda expression is compiled into an anonymous class (...). If a lambda captures variables, the anonymous class will have a field for each captured variable, and a new instance of that class will be created for every invocation. Otherwise, a single instance will be created. The name of the class is derived by adding a suffix from the name of the function in which the lambda is declared (...).
If class Test is a singleton which is used in dagger for example (dependency injection) it will only be initialized once and the second time it will take point to the same object.
https://en.wikipedia.org/wiki/Singleton_pattern

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.

Calling method of innerclass using reflection android java getting InstantiationException

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.

How to choose which constructor to use and what class does the Class<?> type belongs to

I have a class in which i have intialized hashmap in static block. Passing the key, I have retrived the value which is a class. In order to create object for this class. I have used the constructor class to get the constructor and passed arguments and created object.
I have two class in hashmap. To create objectfor EchoExpression I need to pass two arguments and for OutExpression class i need to pass only one argument(String).
Based on the class returned by the key I need to execute which constructor to get and implement, whether the constructor with one argument or two argument.
In EchoExpression, the constructor contains two arguments.
eg:
JXPathExpression check = new JXPathExpression(String expression, Class<?> type)
String belongs to String.class but what class does the Class type argument belongs too? so that i can use it in getting the constructor
public class ExampleFactory {
private static HashMap<String,Class<?>> hmap = new HashMap<String,Class<?>>();
static
{
hmap.put("echo", EchoExpression.class);
hmap.put("Out", OutExpression.class);
}
public void getExpo(String key,String expression)
{
Class aClass =map.get(key);
//Constructor implementation for OutExpression where only one argument string is passed
Constructor constructor = aClass.getConstructor(new Class[]{String.class});
Object object= constructor.newInstance(expression);
//Need constructor for passing two arguments string and class<?> for EchoExpression
return null;
}
}
For such a thing you should in all cases try to have unified constructor parameters or a way to store the parameters per class.
Now for your questions. Class<?> is a reference to a unknown class. Basically to any class. When using it its more or less equal to Class<Object> because all classes got Object as parent.
For using constructors with multiple arguments you first need to fetch the fitting constructor. At this point its already possible to fetch errors that happen in case the class does not support instances with this configuration of arguments.
Fetching the constructor works this way:
aClass.getConstructor(new Class[]{String.class, Object.class, ...});
This works with as many argument types as you like. Creating the new instance of the class then works this way:
constructor.newInstance(theString, theObject, ...);
The function newInstanace is implemented as many arguments as needed. So depending on how many arguments the constructor that was requested requires the newInstance function will be able to work with it.
For all what you intend... maybe a proposal: Maybe its a option not to load the new objects using reflection but rather by storing instances of those objects and returning copies of the objects created using copy constructors or the clone method. In many cases this is less difficult to get running.
Maybe what you are looking for is Class.class like in:
Constructor constructor = aClass.getConstructor(new Class[]{String.class, Class.class});

Java: How to use non-primitive types for constructor.newInstance() in Java Reflection?

After a long day of searching, I still can't figure out how I can instanciate a new object from a selfmade class, if the constructor takes non-primitive arguments. Now I start doubting if this is possible at all?!
In the Documentation of Reflection, they only talk about primitive types (like int, float, boolean, etc.) as far as I saw. And all other information/website/workshop/example I found also just consider primitive types to find the constructor and instanciate a new instance.
So what I want to do is the following (broken down scenario):
Suppose I got a class called MyStupidClass. Another class (let's name it MyUsingClass) takes a MyStupidClass object as argument in the constructor.
Now in my main application, I want to be able to load the MyUsingClass class and instanciate an object out of the constructor.
This is what I found out about "using Reflection" so far:
With empty constructor:
//the MyUsingClass:
public class MyUsingClass {
//the public (empty) constructor
public MyUsingClass() {
...
}
}
In the main application, I would now do something like:
//get the reflection of the MyUsingClass
Class<?> myUsingClassClass = Class.forName("MyUsingClass");
//get the constructor [I use getConstructor() instead of getConstructors(...) here as I know there is only one]
Constructor<?> myUsingClassConstr = myUsingClassClass.getConstructor();
//instanciate the object through the constructor
Object myInstance = myUsingClassConstr.newInstance(null);
Now if I would use some primitive types in MyUsingClass, it would look something like:
//the MyUsingClass:
public class MyUsingClass {
//the public (primitive-only) constructor
public MyUsingClass(String a, int b) {
...
}
}
In the main application, the last line would change to something like:
//instanciate the object through the constructor
Object myInstance = myUsingClassConstr.newInstance(new Object[]{new String("abc"), new Integer(5)});
So far no problems (there might be some small errors in the code above as it is only a broken down example...)
Now the clue question is, how can I create myInstance, if the MyUsingClass looks something like:
//the MyUsingClass:
public class MyUsingClass {
//the public (primitive-only) constructor
public MyUsingClass(String a, int b, MyStupidObject toto) {
...
}
}
? Any help would be appreciated! Thank you already for reading through my question!
greets sv
No problem. Many years ago, I spent a lot of time for this thing too.
You can use Class.newInstance() only if you call default constructor.
In all other cases you have to first find appropriate constructor by calling getConstructor() and the call its newInstance().
When you call getConstructor() use int.class, long.class, boolean.class, etc for primitives. If your class Foo has constructor Foo(int p) you have to say
Constructor c = Foo.class.getConstructor(int.class);
Once you have constructor call it using newInstance():
c.newInstance(12345);
For multi-arguments constructor, say something like:
`c.newInstance(new Object[] {12345, "foo", true})`
Pay attention that we have a luck of autoboxing since java 5. For versions prior to 5, we had to use more verbose syntax:
`c.newInstance(new Object[] {new Integer(12345), "foo", new Boolean(true)})`
i.e. we used int.class to locate constructor and Integer type to call it.
I hope this helps.
The same way you called the constructor for the other types:
Object myInstance = myUsingClassConstr.newInstance(new Object[] {
new String("abc"),
new Integer(5),
new MyStupidObject()
});
From the Constructor.newInstance documentation:
Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor's declaring class, with the specified initialization parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary.
Reference types are specifically listed there, and require no special treatment.
Ok, this (all the answers) helped me alot. It's working now, at least at first glance. Will need some further testing, but I hope I well get through this alone now!
Thank you very much...
[They could be more specific on this topic in the specifications, though]

Categories

Resources