Scala extend trait field not found - java

I have a scala trait with a public UUID that has a default value:
trait pet {
var uuid_ : UUID = UUID.randomUUID
}
now I am creating multiple classes, also in scala:
class dog extends pet {
var foo = 1
}
class cat extends pet {
}
class fish extends pet {
}
After that I created a method in Java (old project with both languages mixed).
Here the snipped with my problem. In the variable somePet is an instance of dog, cat or fish. But it is not clear what of them exactly:
// printing all variables in the console for human testing
Serializer.printAllFields(somePet);
// The somePet Variable must be a pet
if(!pet.class.isAssignableFrom(somePet.getClass()))
throw new Exception("Not a pet.");
// get the UUID of the pet
UUID uuid_;
try {
Field f = pet.class.getField("uuid_");
f.setAccessible(true);
uuid_ = (UUID) f.get(somePet);
}catch(Exception e){
// no uuid found
throw e;
}
But when I run the code I get the following error:
Exception in thread "main" java.lang.NoSuchFieldException: uuid_
And the stacktrace points on the line with Field f = pet.class.getField("uuid_");.
But what is wrong with the code?
An alternative I thought was replacing this exact line with:
Field f = ntObj.getClass().getField("uuid_");
But this also fails.
So where is the variable uuid_?
Because when I print out all variables in the console of the current somePet with a Serializer, I get something like
* cat.uuid_ = 34d7a781-472d-4d98-861e-7cff08045445;
or
* dog.foo = 1
* dog.uuid_ = 34d7a781-472d-4d98-861e-7cff08045445;
in the console.
So the variable uuid_ is there with a default value.
(I am using the serializer from this post)
So how do I get the uuid_ variable in my java snippet?

First of all, there is no such Serializer under the the package java.util, so you're using something else.
An trait is translated to a Java interface, which cannot have fields per se.
However you're trying to access the field via the Pet interface
pet.class.getField(...)
That won't work. You need to look for the field inside the concrete class.
Also, the field will be private by default, since the access is granted via a getter.
The getField method is able to retrieve every public field for the entire class hierarchy (which mean even superclasses), while getDeclaredField is able to retrieve protected and private fields, but only on the exact class you're calling it from. You need also a call to setAccessible(true), because
A value of true indicates that the reflected object should suppress
Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks
The correct code would be (dog is the concrete instance)
final Field uuid = dog.getClass().getDeclaredField("uuid_");
uuid.setAccessible(true);
final Object o = uuid.get(dog);
Or using the automatic getter
final Method uuid = dog.getClass().getMethod("uuid_");
final Object o = uuid_.invoke(dog);

Related

Create Object using the value of a Java variable

I need help I need to know if Java allows to create an object dynamically, using the value of a variable.
Example
// I have 2 classes:
public class Audit {
private Long idAudit
// constructors, get and set
}
publish class Example {
private Long idExample
// constructors, get and set
}
-------------------------------------------------- -----
// create Audit and Example class object
Audit objAudit = new Audit ();
Example objExample = new Example ();
my question is the following can you create an object either of type Audit or example using the value of a variable as I try to do in the following example. Example:
String className = "Audit"; // variable that contains the class of the Object to create
className auditObject = new ClassName (); // I use the variable classname to create the desired object
Clearly I get an error trying to create the object that way, my question is can I create an object dynamically or some other option to try to achieve what I need. Thank you
Reflection is what you are searching for
final String className = "Audit";
final Class<?> clazz = Class.forName(className);
final Object o = clazz.getConstructor().newInstance();
There are several ways you can do this.
One is called reflection, and I will let you read about it on your own.
The other one is called a factory pattern. You can create a class called ObjectFactory. in that class you will have a method public Object createObject(String type).
In the method you can check if the type you received is one of your known types, and based on the type you can create the instance of the correct class. It is better of your classes implement the same interface. Then of course your method would return the instance of that interface (or a common base class).

Android Java, How to get the value of class attribute?

I want to get the value a class attribute, But I am getting exception : java.lang.NoSuchFieldException
Person.class
public class Person {
public static final String name = "person name";
}
MainActivity.class
...
private void method() {
Class myClass = Person.class;
String name = myClass.getField("name");
}
...
I am getting a java.lang.NoSuchFieldException exception for the getField method.
I tried these solutions but with no avail ...
Change getField method to getDeclaredField
Surround the code by try/catch, and got another error (Incompatible types : java.lang.String and java.lang.reflect.Field)
Invalidate Android Studio caches and restart
I don't Know how to access this value, Any solutions or suggestions are welcomed.
Thanks in advance.
Change getField method to getDeclaredField
Surround the code by try/catch, and got another error (Incompatible
types : java.lang.String and java.lang.reflect.Field)
that because getDeclaredField will return object of type Field not String,
just change your code to this
Field field = myClass.getDeclaredField("name");
//do something with field
If you want to access the value of the field, you can use the get(...) method with a null argument - since it's a static field, it does not require any instance:
private void method() {
Class myClass = Person.class;
Field field = myClass.getField("name");
String name = field.get(null);
Log.d("Test", "field value: " + name);
}
In your case, it doesn't matter whether you use getField(...) or getDeclaredField(...). You would want to use the latter if you want to grab a field in its superclass or an interface implemented by your class.
For example, if Person were to extend from a class that has a field named sample, you would need to use getDeclaredField("sample") instead.
If your variable in the class "Person" is static:
(This is not the best solution in my opinion)Explanation: getField method returns a type "field" so you CAN NOT save into a variable from another type without a conversion.
YourField.get returns an object so you CAN NOT save into a variable from another type without a conversion.
try{
Class _person = Person.class;
Field field = _person.getField("name");
Object value = field.get(null);
String valueString = (String)value; /*The String you are looking for*/
}catch (Exception e) {
//TODO handle exception
}
If your variable in the class "Person" is static:
String valueString = Person.name /*The value you are looking for*/
If your variable isn't static but public:
IMPORTANT (If you have not set a default value to the variable): In this case the value will be an empty string because you are creating a new instance of your calss. You can set the "person name" in the constructor of your Person class another way you will get an empty string because the variable isn't static.
Person _person = new Person();
String personName = _person.name;
Since that's a constant you declared, access it directly with the class name as below,
String name = Person.name;
It's a static constant. Static means there is only one value at a time possible. Or say it like this: The class attribute 'name' is a class attribute, not an object attribute! The attribute belongs to the class!
So you don't need to create an instance of your Person class.
You just can use:
String name = Person.name;
Remember: this only works cause the name belongs to the class. And it does so, because you declared your name variable static.

What are the differences between Kotlin class properties and Java class fields

I've started to learn Kotlin. My current background is Java. I found out that class properties in Kotlin are quite different from class fields in Java, even though they look similar. In his question I would like to gather together all technical differences between those two. This is what I’ve already figured out:
Java field and hiding vs Kotli properties and overriding
(and actually this pushed me to write this post):
In Java, a field of a base class is hidden by a field with the same name in derived class, so which field is used depends on the type of a reference to the object which contains the field, not the type of the object itself (fields are not overridden like methods are, so they don't depend on runtime type of an object). For example this code:
class A {
public String name = "A";
public void printMessage() {
System.out.println("Field accessed in method declared inside class A invoked form an object of " + getClass() + " : " + name);
}
}
class B extends A{
public String name = "B";
}
public class Main {
public static void main(String... args){
B b = new B();
System.out.println("Field from instance of class B pointed by reference to B : " + b.name);
A a = b;
System.out.println("Field from instance of class B pointed by reference to A : "+a.name);
a.printMessage();
}
}
prints this :
Field from instance of class B pointed by reference to B : B
Field from instance of class B pointed by reference to A : A
Field accessed in method declared inside class A invoked form an object of class B : A
In contrast Kotlin properties are fields accessed by automatically generated getters and setters. Properties are overridden (not hidden), so property access is resolved at runtime, and the code with similar meaning as above written in Kotlin:
open class A {
open val name = "A"
fun printMessage() {
println("Field accessed in method declared inside class A invoked form an object of $javaClass : $name")
}
}
class B(override val name : String = "B") : A()
fun main(args : Array<String>) {
val b : B = B()
println("Field from instance of class B pointed by reference to B : " + b.name)
val a : A = b;
println("Field from instance of class B pointed by reference to A : " + a.name)
a.printMessage()
}
prints this :
Field from instance of class B pointed by reference to B : B
Field from instance of class B pointed by reference to A : B
Field accessed in method declared inside class A invoked form an object of class B : B
Access level
Java fields are package – private by default. Kotlin properties are public by default.
Default initialization
Java fields are initialized with reasonable default values (as describet here : https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html).
Every Kotlin class property has to be created in a way which will allow it to provide explicitly given value when it will be accessed.
One can achieve this by initiallizer, constructor, setter, lazy initialization:
class InitValues(val inCtor : String = "Given in constructor"){
var byInitializer = "In initializer"
var initializedWithNull : String? = null
val valueGivenByGetter
get() : String {
return "This value is given by getter"
}
val byLazyInit : String by lazy { "This is lazy init" }
}
but value which should be returned has to be given – no defaults will be provided.
Are there any other technical differences regarding class fields / properties which may surprise Java programmer writing code in Kotlin?
(I’m not talking about additional features like for example delegated properties but those things which at first glance are similar to what exists in Java and can be delusive)
I would like to elaborate more on the differences between a Java field and a Kotlin Property. Have a look at the following examples of Java field and Kotlin property.
Examples
Java field:
class Product {
public int discount = 20;
}
Kotlin property:
class Product {
var discount: Int = 20
}
Auto-generated Accessors
The two examples above are not equivalent. Because in Kotlin, getters and setters are auto-generated for the properties. The Kotlin property above is equivalent to the following Java code:
class Product {
private int discount = 20;
public int getDiscount() {
return discount;
}
public void setDiscount(int discount) {
this.discount = discount;
}
}
So the difference between the Java field and Kotlin Property is that the Kotlin property creates a field and its accessors. When the property is a val, it creates a getter only. When the property is a var, it creates both a getter and a setter. And the field becomes private by default as shown in the above code, the discount is private. But you can access the discount using its getters and setters.
Custom Accessors
What if we want to implement some logic or validation inside the getters and setters in Kotlin? For example, when someone is setting the discount on the product, we want to make sure it's never above 85%. In this case, we can define the custom accessors for the discount property like following:
class Product {
var discount: Int = 20
set(value) {
if (value >= 85) {
field = 85
} else {
field = value
}
}
}
The field is a reserved keyword in Kotlin which holds the value as a backing field. The above code result in:
product.discount = 70;
println(product.discount) // 70
product.discount = 90;
println(product.discount) // 85
We can do similar things with the getter using the get() method.
That's it! Hope that helps.

Java run time class reflection

Say if I have a class named Car I can use the following line of code in certain situations.
Car.class
My question is there a way I can make the same type of call if a user supplies a class name at run time. Have tried something similar to the below but no joy, is there a way i can do it.
String className = "Car";
Class.forName(className ).class;
Also I need to be able to cast dynamically, if the user specifies a list of objects I need to be able to dynamically cast.
e.g. instead of Car myCar = (Car) object
I need to be able to have to the user specify the name/type of class at run time so that I need to be able to do something along the lines of ClassName myObj = (ClassName) object.
Class.forName("Car") already returns the same as Car.class.
For casting, you can then use Class.forName("Car").cast(object), which would return a Car object. Take a look at the API, mostly the java.lang.Class part of it.
Also, since you're casting # runtime, there's no type safety, and you should check whether object extends or implements Car before doing it, otherwise you'll get an exception. A question I asked ~ a year ago and the answers there may be relevant to you as well.
Though, as others already said, this smells & you could probably redesign it in a better way, also note that this type of casting will typically be pretty slow because Java needs to examine the type hierarchy (it needs to throw a ClassCastException if it can't cast to Car).
Given the nature of the question, most of the answers to this are straight from the Reflection API documentation. I would suggest you take a look at this: http://docs.oracle.com/javase/tutorial/reflect/class/index.html. If this does not help and you need help with something specific, we can look at that.
What you are looking for is a feature called Reflection in the Java programming language.
It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
A Simple Example from http://java.sun.com
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
For an invocation of:
java DumpMethods java.util.Stack
the output is:
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
Here is an example of creating objects at runtime:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
You can read more about it here and here - for indepth view
Also look here:
What is reflection and why is it useful?
You want to interact with myObj, so rather than going through these gymnastics, think about adding an interface that models the interactions you want to have with the objects, then use that interface in the code. The classes supplied by the user can then be validated to implement the necessary interface and errors raised appropriately.
The expression Car.class returns the java.lang.Class object for class Car.
A statement Class.forName("Car") will also return the java.lang.Class object for class Car (assuming that class Car is in the default package). Note: No need to append .class; that would give you the Class object of class Class itself, which is not what you want.
Class Class has methods to check if an object is an instance of the class that the Class instance represents (hope this is not too confusing...). Since you don't know the name of class Car at compile time, you're not going to have any kind of compile time type safety.
Lookup the API documentation of java.lang.Class.

java.lang.NoSuchFieldException: when using reflection

public static <A, B> B convert(A instance,
Class<B> targetClass) throws Exception {
B target = (B)targetClass.newInstance();
for (Field targetField : targetClass.getDeclaredFields()) {
targetField.setAccessible(true);
Field field =
instance.getClass().getDeclaredField(targetField.getName());
field.setAccessible(true);
targetField.set(target, field.get(instance));
}
return target;
}
Above is the code I get from forum, When I try to reflect an single type object it works, but when I try on the complex type which mean inside ClassA I got ClassB object, I got the java.lang.NoSuchFieldException. Can anyone help me?
You have two different classes, with, most likely, different set of fields.
So if your Class A doesn't have the same fields as your class B, then the exception is thrown.
I'd suggest using BeanUtils.copyProperties(source, target) from apache commons-beanutils. You just create the second object yourself, and pass it to the method. It will not throw an exception if fields differ.
What is your ultimate goal with this piece of code?
Two suggestion:
(1) You can drop the downcast at the first line of the method:
B target = targetClass.newInstance();
(2) Add a try catch so that you can see the name of the missing field. This will help you sort out the issue you're having:
Field field = null;
try {
field = instance.getClass().getDeclaredField(targetField.getName());
}
catch(NoSuchFieldException e) {
throw new RuntimeException("Didn't find field named '" + targetField.getName() + "'");
}
...
Another answer.
If I understand your comment correctly it seems that you have inner classes: Class B (Target) is a class that is defined inside class A. Something like this:
class A {
int n;
class B {
int n;
}
}
Although these two classes seem to have the same fields, and therefore - should not inude a field not found error - they are not.
Inner classes (unless they are defined as static) has a hidden field inserted by the compiler. This field is of the type of the outer class and points to the object that created the inner class object. When using reflection this field is exposed. As A does not have such field, an exception is raised.

Categories

Resources