is it possible to get the final parameter values from an anonymous class? Using reflection or anything else?
This example is of course all made up:
final String x = "Param1";
final String y = "Param2";
ITest<String> iTest = new ITest<String>() {
#Override
public String execute() {
return t.testMethod(x, y);
}
};
// Get values or x and y from iTest here?
So this is your code:
ITest<String> iTest = new ITest<String>() {
#Override
public String execute() {
return testMethod(x, y);
}
};
Try defining ITest like so:
public class ITest {
int x;
int y;
public testMethod(int x, int y) {
this.x = x; this.y = y;
}
// execute somewhere
}
I haven't tried this myself, but I believe that the values of x and y are copied into autogenerated fields in the anonymous class instance. Try this:
for (Field field : iTest.getClass().getDeclaredFields()) {
field.setAccessible(true);
System.out.println(field.getName() + ": " + field.get(iTest));
}
Related
Main:
public class Main {
public static void main(String [] args) {
Foo<String, Location> foo = new Foo<>();
foo.add("abc", new Location(5, 6));
}
}
Location:
public class Location {
public int x;
public int y;
public Location(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return "(" + x + "," + y + ")";
}
}
Foo class:
public class Foo<K, T> {
public void add(K name, T loc) {
System.out.println(name + " " + loc.x + loc.y);
}
}
When I try to run the program I get the "question title" error, I don't know what that happens, and how to fix that.
One way is to use instanceof operator if you are expecting a type that you know. This is a demo.
public void add(K name, T loc) {
if(loc instanceof Location) {
System.out.println(name + " " + ((Location)loc).x + ((Location)loc).y);
}
}
UPDATE
As Stephen C mentioned that Foo class potentially needs hard-coded knowledge of the capabilities of each of the possible types T. Which is (in theory) every Java reference type! The correct way to solve this is to declare <T extends SomeInterface> and provide getters in the interface to get the x and y attributes
So instead of knowing about all possible types of T we can make T extend SomeInterface and get the information by calling the getters which can be implemented in the respective type.
Make T extend LocationInfo interface to get info about x and y
class Foo<K, T extends LocationInfo> {
public void add(K name, T loc) {
System.out.println(name + " " + loc.getX() + loc.getY());
}
}
interface LocationInfo {
int getX();
int getY();
}
And include the implementation in Location class
class Location implements LocationInfo {
public int x;
public int y;
public Location(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return "(" + x + "," + y + ")";
}
public int getX() { return x; }
public int getY() { return y; }
}
For example, I have got a code like this:
class Point
{
private String x;
private String y;
public String getX () { //Here can not use Optional<String>
return this.x;
}
public String getY () {
return this.y;
}
public Point(String x, String y) {
this.x = x;
this.y = y;
}
}
...
Point point = new Point(null, "14.2");
if(ofNullable(point.getX().isPresent()) {
this.xCoordinate = point.getX();
}
if(ofNullable(point.getY().isPresent()) {
this.yCoordinate = point.getY();
}
I want to do it in a cleaner way, something like this:
this.x = ofNullable(point.getX()).ifPresent((x) -> x)
I know this is not working but I tried almost everything but I can not get it to work.
You have to use Integer instead of the primitive type int
You didn't post enough code, but your getX method definition should be:
Optional<Integer> getX() instead of int getX().
If you can't modify the class with the method, create a wrapper class or something. Without seeing all the code, I can't say much more...
EDIT:
Make your point class store optional values:
class Point
{
private Optional<String> x;
private Optional<String> y;
public Optional<String> getX () { //Here can not use Optional<String>
return this.x;
}
public Optional<String> getY () {
return this.y;
}
public Point(String x, String y) {
this.x = ofNullable(x);
this.y = ofNullable(y);
}
}
Then:
Point point = new Point(null, "14.2");
if(point.getX().isPresent()) {
this.xCoordinate = point.getX();
}
if(point.getY().isPresent()) {
this.yCoordinate = point.getY();
}
Here's the code
class TwoD {
int x, y;
public TwoD(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
class ThreeD extends TwoD {
int z;
public ThreeD(int x, int y, int z) {
super(x, y);
this.z = z;
}
}
class FourD extends ThreeD {
int t;
public FourD(int x, int y, int z, int t) {
super(x, y, z);
this.t = t;
}
}
class coords<T extends TwoD> {
T cordinates;
public coords(T cordinates) {
super();
this.cordinates = cordinates;
}
static void show(coords<? super ThreeD> c) {}
}
public class mainX {
public static void main(String a[]) {
FourD fourD = new FourD(1, 2,3,4);
coords check = new coords(fourD);
coords.show(check);
TwoD twoD = new TwoD(1, 2);
coords check1 = new coords(twoD);
coords.show(check1);
// How this program runs fine with the child and parent subclass objects in show method?
}
}
The method
static void show(coords c)
should only allow Parent class objects ? Why is it allowing child class objects also?
How this program runs fine with the child and parent subhclass objects in show method?
I am confused!
As mentioned by #Thomas in the comments, you're using raw types for your coords. (I could go into detail, but the linked answer explains everything very clearly. Your use case is mainly mentioned in the sections How's a raw type different from using <?> as a type parameter? and A raw type is the erasure of that type.)
If you'd change:
coords check = new coords(fourD);
...
coords check1 = new coords(twoD);
To:
coords<FourD> check = new coords<>(fourD);
...
coords<TwoD> check1 = new coords<>(twoD);
You would get the error you'd expect:
error: incompatible types: coords<TwoD> cannot be converted to coords<? extends ThreeD>
coords.show(check1);
^
PS/off-topic: Class coords should be with a capital C (thus Coords) when following Java's code standards.
Please help me out with the code the error is
class SubclassInSamePackage is public, should be declared in a file named SubclassInSamePackage.java
Program:
package pckage1;
class BaseClass {
public int x = 10;
private int y = 10;
protected int z = 10;
int a = 10; //Implicit Default Access Modifier
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
private int getY() {
return y;
}
private void setY(int y) {
this.y = y;
}
protected int getZ() {
return z;
}
protected void setZ(int z) {
this.z = z;
}
int getA() {
return a;
}
void setA(int a) {
this.a = a;
}
}
public class SubclassInSamePackage extends BaseClass {
public static void main(String args[]) {
BaseClass rr = new BaseClass();
rr.z = 0;
SubclassInSamePackage subClassObj = new SubclassInSamePackage();
//Access Modifiers - Public
System.out.println("Value of x is : " + subClassObj.x);
subClassObj.setX(20);
System.out.println("Value of x is : " + subClassObj.x);
//Access Modifiers - Public
// If we remove the comments it would result in a compilaton
// error as the fields and methods being accessed are private
/* System.out.println("Value of y is : "+subClassObj.y);
subClassObj.setY(20);
System.out.println("Value of y is : "+subClassObj.y);*/
//Access Modifiers - Protected
System.out.println("Value of z is : " + subClassObj.z);
subClassObj.setZ(30);
System.out.println("Value of z is : " + subClassObj.z);
//Access Modifiers - Default
System.out.println("Value of x is : " + subClassObj.a);
subClassObj.setA(20);
System.out.println("Value of x is : " + subClassObj.a);
}
}
There can be only one public class in a file and the name of that class should match with that of the filename.
If you want to create multiple classes in the same file, you can mark them as private or "blank" but not public.
I need to create and populate an object inside a method. The only information is the member field name (passed as a string) and the relevant value for that field (passed as an Object). What is the most appropriate design pattern taking into account performance? - reflection, if comes with a penalty, would not be a preferred approach.
Update:
The value to be set comes from an object that acts as a generator of the values having a set of methods that return the proper value for the specific field. E.g. for member Double x; it would be generator.getX()
A simple function to copy all the getters to all the available setters is as follows. With some more work you can cache this information and speed it up but it is likely to be fast enough as it is.
public static <T> T copyTo(Object from, T to) {
for(Method m : to.getClass().getMethods()) {
if (!m.getName().startsWith("set") || m.getParameterCount() != 1)
continue;
try {
Method getter = from.getClass().getMethod("g" + m.getName().substring(1));
m.invoke(to, getter.invoke(from));
} catch (NoSuchMethodException ignored) {
// ignored
} catch (InvocationTargetException | IllegalAccessException e) {
throw new AssertionError(e);
}
}
return to;
}
Note: Only the fields where there is a matching getter and setter will attempt to copy from one to the other.
public static void main(String[] args) {
One orig = new One(1, "hi", 3);
One to = new One();
One copy = copyTo(orig, to);
System.out.println(to);
}
static class One {
int x;
String y;
double z;
public One() {
}
public One(int x, String y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
#Override
public String toString() {
return "One{" +
"x=" + x +
", y='" + y + '\'' +
", z=" + z +
'}';
}
}
prints
One{x=1, y='hi', z=3.0}
If you want to create an object generically you need to use reflection.
The only alternative is byte code generation which will be much more complex to implement and only save you a fraction of a micro-second.
How many days is it worth sending to implement this to save a micro-second?
If you know the class name of the object then what you can do is:
public Object populate(String className,String fieldName,Object value) throws Exception{
Class clazz = Class.forName(className);
Object o = null;
for(Field f: clazz.getFields()){
if(f.getName().equals(fieldName)){
o = clazz.getConstructor().newInstance();//default constructor if it exists
f.set(o, value);
break;
}
}
return o;
}
EDIT:
Since you know the class(comment under question) then you can use is the function I wrote just with this change and not className parameter:
Class clazz = Class.forName(YourClass.class.getName());
EDIT2:
If I understand the update you are asking about how to know which method to invoke to get the value.
On your generator class you can get the list of methods it has. Then if your method are named getFieldName() you can once you have the field name find the method with the name getFiledName.
Example:
for(Method m:GeneratorClass.class.getMethods()){
System.out.println(m.getName());
//analyze method name and field name to determine which method to call
//..
boolean callThis = true;//result of analysis
if(callThis){
//Object value = m.invoke(obj);
//obj==generator
}
}