Load a class using reflection and edit the variables during runtime [duplicate] - java

Okay, so I have a java file which is loading another class and I want the java file to be able to edit and read variables from the class which is running.
For example:
I have a button which when pressed it sets a variable (This is the class file). I want the java file which is loading this class to be able to see the new value of the variable read it, set it and do whatever is needed. And I want the new value which is set to show up on the running java class.
This is what I have tried so far but when I try to edit the values like getting baseX it doesn't show up on the running class. Also, the baseX value should change when I do stuff on the running class but the stuff is not printed to the screen when I change them. It's as if reflection can't read stuff on runtime. So what does?
Class c = Class.forName("Client");
for (Method m : c.getMethods()) {
if (m.getName().contentEquals("main")) {
Object[] passedArgs = { args };
m.invoke(null, passedArgs);
}
}
Object instance = c.newInstance();
Field baseX = c.getField("baseX");
Field loggedIn = c.getField("loggedIn");
boolean gotValues = false;
while(!gotValues) {
boolean loggedin = loggedIn.getBoolean(instance);
if(loggedin) {
System.out.println(baseX.get(instance));
} else {
System.out.println(loggedin);
loggedIn.setBoolean(instance, true);
}
}
Also yeah getter/setter methods would work if they worked on runtime and I could make it so that when button x is pressed variable y changes on screen. What is a java bean? Also what if I wanted to just invoke a method and not get a value? Or what if I wanted to add my own methods/code?

Try this:
public class Client {
public Object baseX = new Object();
public boolean loggedIn;
}
-----
public class Main {
public static void main(String[] args) throws Exception {
Class c = Class.forName("Client");
/*for (Method m : c.getMethods()) {
if (m.getName().contentEquals("main")) {
Object[] passedArgs = {args};
m.invoke(null, passedArgs);
}
}*/
Object instance = c.newInstance();
Field baseX = c.getField("baseX");
Field loggedIn = c.getField("loggedIn");
boolean gotValues = false;
//while (!gotValues) {
boolean loggedin = loggedIn.getBoolean(instance);
if (loggedin) {
System.out.println("Logged in!");
System.out.println(baseX.get(instance));
}
else {
System.out.println("NOT Logged in!");
System.out.println(loggedin);
loggedIn.setBoolean(instance, true);
System.out.println(loggedIn.getBoolean(instance));
}
//}
}
}

Related

In Reflection, Method object's parameter class doesn't match argument class?

[This post has been edited to include a simplified copy/paste version of the underlying issue.]
I'm working on a Reflection project that will have some functionality similar to JUnit, but I'm running into an obstacle where the program seems to feel I have 2 different versions of the same class.
I've written a simple Car class as follows.
public class Car {
private String name;
public Car(String n) {
name = n;
System.out.println(name + " was constructed.");
}
public void honk() {
System.out.println("beep beep");
}
public void crash(Car other) {
System.out.println(name + " crashes into " + other.name);
}
}
I can successfully test the functionality of the car like this:
public class CarRunner {
public static void main(String[] args) {
Car a = new Car("Model T");
Car b = new Car("Tesla");
a.honk(); //prints "beep beep"
a.crash(b); //prints "Model T crashes into Tesla"
}
}
All the stuff above works fine.
Now, I want to reproduce the results of CarRuner but with some functionality testing methods I've written using reflection. Using reflection, I can request the creation of object and invoking methods with those objects. It works great until the final test, when a user-defined class is used as an argument.
import java.io.*;
import java.lang.invoke.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import java.net.*;
public class TesterTool {
//Where are the class files that I am testing?
private static File classPath = new File("C:\\Users\\Spatter\\Desktop\\Autograder\\SimpleCarDemo");
public static Object makeObject(String nameOfClass, Object[] arguments) {
Object retObject = null; //goal is to get an object in here of the requested class.
try {
//What type of object are we trying to construct?
URL classUrl = classPath.toURI().toURL();
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{classUrl});
Class<?> c = Class.forName(nameOfClass, true, classLoader);
//What kind of arguments do we have?
Class[] argumentTypes = new Class[arguments.length];
for (int i = 0; i < arguments.length; i++) {
argumentTypes[i] = arguments[i].getClass();
}
//Lets find a constructor that can accept the type of arguments we have
Constructor con = c.getConstructor(argumentTypes);
FutureTask<?> theTask = new FutureTask<Object>(new Callable<Object>()
{
public Object call() {
Object retObject = null;
try {
retObject = con.newInstance(arguments);
} catch (Exception e) { return e; }
return retObject;
}
});
ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(theTask);
retObject = theTask.get(3, TimeUnit.SECONDS);
es.shutdownNow();
if (retObject instanceof Exception) throw new Exception();
} catch (Exception e) {
System.out.print("Error: Unable to construct object" + e);
}
return retObject;
}
public static Object testMethod(Object invokingObject, String methodName, Object[] arguments) {
Object retObject = null; //if the method we test returns an object, we will do the same.
try {
//What type of object are we trying to construct?
Class c = invokingObject.getClass();
//Alternate version of getting class type using ClassLoader
//Class originalc = invokingObject.getClass();
//String nameOfClass = originalc.getName();
//URL classUrl = classPath.toURI().toURL();
//URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{classUrl});
//Class<?> c = Class.forName(nameOfClass, true, classLoader);
//What kind of arguments do we have?
Class[] argumentTypes = new Class[arguments.length];
for (int i = 0; i < arguments.length; i++) {
argumentTypes[i] = arguments[i].getClass();
}
//Lets find a method that can accept the type of arguments we have
Method m = c.getMethod(methodName, argumentTypes);
FutureTask<?> theTask = new FutureTask<Object>(new Callable<Object>()
{
public Object call() {
Object retObject = null;
try {
retObject = m.invoke(invokingObject, arguments);
} catch (Exception e) { return e; }
return retObject;
}
});
ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(theTask);
retObject = theTask.get(3, TimeUnit.SECONDS);
es.shutdownNow();
if (retObject instanceof Exception) throw new Exception();
} catch (Exception e) {
System.out.print("Error: Unable to run method " + e);
}
return retObject;
}
public static void main(String[] args) {
//Find the Car class and invoke the constructor that receives a String parameter.
Object o1 = makeObject("Car", new Object[]{"Model T"}); //this works fine.
Object o2 = makeObject("Car", new Object[]{"Tesla"}); //this works fine.
//Invoke the honk method of object o1. No parameters required.
//The result is that "beep beep" is printed.
testMethod(o1, "honk", new Object[] {}); //this works fine.
//Invoke the crash(Car c) method of o1 using o2 as the parameter.
//This should print "Model T crashes into Tesla".
testMethod(o1, "crash", new Object[] {o2}); //this doesn't work.
}
}
This last test is where my problem is coming into play. testMethod appears to be unable to find a version of the crash method that matches my request. The crash method is supposed to receive a Car object, which it does, but it doesn't seem to be good enough.
I've also tried a very complex alternate version of this where I get all the methods of the Car class and try to find one that matches the signature, but it seems to feel that an object of Class car isn't an object of Class car. (See below.)
Class objectClass = o2.getClass();
Class[] paramTypes = method.getParameterTypes(); //where method is the Method object for crash
Class paramClass = paramTypes[0]; //there was only 1 paramType. I confirmed that it's the Car class.
System.out.println(objectClass); //prints class Car
System.out.println(paramClass); //prints class Car
if (paramClass.isAssignableFrom(objectClass)) { //always returns false?
System.out.println("I want to run this method because the signature matches.");
// o1 should invoke method using FutureTask
}
isAssignableFrom() always returns false, even though they are both Car classes. Any idea what might be the problem? I've inspected the both of the Class objects (objectClass and paramClass) and they appear to be identical, even down to the paths in the ClassLoaders.
Instead of isAssignableFrom(), I've also tried isInstance, but it didn't work either:
if (paramClass.isInstance(o2)) { //also always returns false
The problem was coming from creating a new URLClassLoader object each time I was locating a Class object. By having only 1 URLClassLoader as a static variable the issue is resolved.

Restart main function of a java server [duplicate]

This question already has answers here:
cannot make a static reference to the non-static field
(7 answers)
Closed 5 years ago.
I'm working on my first Server/Client Project in Java. It's still very Basic and I was able to Exchange some data between the Server and the Client program.
Now I facing Trouble to reconnect once the Client has terminated the Connection.
I'm comfing from Visual Basic where I just would have had a timer and a boolean, checking if a Connection was established or not and eventually reset the socket.
I tried something similar in Java by Setting up a Start method and a Restart method and just checking in a Loop what's the Status of the boolean.
Unfortunately, eclipse keeps giving me the message that I cannot make a static reference to a non-static field. Now I'm totally lost.
Here's the server's code which works fine once but cannot be restarted.
package ComplexChatServer;
public class MainRoutine {
public Boolean boIsRunning;
public ConnectionHandlerS chsEins;
public Boolean boConnected = false;
public String strText;
public void StartRunning() {
boIsRunning = true;
chsEins = new ConnectionHandlerS();
chsEins.SocketListener();
}
public void ContinueRunning() {
boConnected = chsEins.getClientStatus();
if (boConnected == true) {
//System.out.println("Connected");
strText = null;
strText = chsEins.ReadInput();
if (strText != null && strText.isEmpty() == false) {
System.out.println("Loop");
System.out.println(strText);
strText = "";
boIsRunning = true;
}
else if (strText.equalsIgnoreCase("+++END+++")) {
boIsRunning = false;
System.exit(0);
}
}
else {
//System.out.println("Not connected");
}
}
public static void main (String [] args) {
int intRun;
while (true) {
if (boIsRunning = true) {
intRun = 1;
}
else {
intRun = 0;
}
switch (intRun) {
case 0:
StartRunning();
break;
case 1:
ContinueRunning();
break;
}
}
}
}
You can not make a static call to a non-static member. A static member in Java is a member that belongs to a class itself; not belonging to its objects. So you either have to instantiate a MainRoutine object and call it's methods or turn your existing methods into static ones to be able to call them from your already static main method; depending on what you want to achieve.
Besides that, conventionally Java community uses camel casing when naming methods and variables. Please check the syntactic and logical correction below:
public static void main (String [] args) {
MainRoutine routine = new MainRoutine();
while(true) {
if(boIsRunning) {
routine.continueRunning();
} else {
routine.startRunning();
}
}
}
Also as #Bill Horvath stated in his comment, notice that you're actually exiting the process rather than restarting it.

Creating array of methods returning boolean and iterating through for-each loop

Okay so I have a batch of methods returning boolean values of true/false.
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
updateMainTabsAccess();
updateUserPaymentTabPermissions();
updateUserRegistrationTabPermissions();
updateUserStudentsTabPermissions();
updateUserFacultyTabPermissions();
updateUserHomePermissions(); //saves any update made on existing user settings/permissions
updateUserInformation(); // sasve any update made on existing user information such as username
}
I would like to know if it's possible for me to check each of the methods' return value through a for-each loop.
I'm thinking of creating a private boolean isUpdateSuccessful() method.
Say like,
private boolean isUpdateSuccessful(){
Boolean a = updateMainTabsAccess();
Boolean b = updateUserPaymentTabPermissions();
//........so on....
Boolean result = (a && b &&...)
return result;
}
Problem is, I don't know if it's possible to put them in an arraylist or component array like
ArrayList<Boolean> listOfMethods = new ArrayList<Boolean>(method1,method2..);
So that I can then check each through a for-each loop
for(Boolean b:listOfMethods){
Boolean successful=true;
successful = (successful && b)
}
My questions are:
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
I'd appreciate any answer or suggestion. I simply want to check if every method was successful. I thought of using ?1:0:
Thanks in advance.
If I am you, I would do this. Just a sample code:
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (updateMainTabsAccess()) {
if (updateUserPaymentTabPermissions()) {
if (updateUserRegistrationTabPermissions()) {
...
} else {
// error on update registration
}
} else {
// error on update payment
}
}
With the above style:
You don't execute other methods when the before one fails.
Can have detailed error messages for each error.
You need not to main a collection and iteration.
Why not use a Stream to check the results:
Stream.<Boolean>of(updateMainTabsAccess(),
updateUserPaymentTabPermissions(),
updateUserRegistrationTabPermissions(),
updateUserStudentsTabPermissions(),
updateUserFacultyTabPermissions(),
updateUserHomePermissions(),
updateUserInformation()).allMatch(b -> b);
this way you get rid of short circuit evaluation and also don't need to create method references for each method.
method references
List<Supplier<Boolean>> methods = Arrays.asList(this::updateMainTabsAccess,
this::updateUserPaymentTabPermissions,
...
);
for (Supplier<Boolean> supplier : methods) {
boolean methodResult = supplier.get();
...
}
This can hardly be considered an improvement though...
this will find all method in side your class which is return Boolean after automatically invoke method one by one and store response to successful variable
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class Test {
public static void main(String[] args) {
Test test = new Test();
Class c = test.getClass();
boolean successful = true;
for (Method method : c.getDeclaredMethods()) {
if (method.getReturnType().toString().equals("boolean")) {
try {
String mname = method.getName();
Object o = method.invoke(test, null);
System.out.format("%s() returned %b%n", mname, (Boolean) o);
successful = successful && (Boolean) o;
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("final answer : " + successful);
}
public boolean a() {
return true;
}
public boolean b() {
return false;
}
public boolean c() {
return false;
}
}
Hope its help to you.
If you want every method to be executed and check if every method scucceded you could simply write
boolean success = updateMainTabsAccess() &
updateUserPaymentTabPermissions() &
updateUserRegistrationTabPermissions() &
updateUserStudentsTabPermissions() &
updateUserFacultyTabPermissions() &
updateUserHomePermissions() &
updateUserInformation();
You have already received some answers.
Fabian's is a good one if you are using java 8.
But to answer directly your points
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
ArrayList<Boolean> resultsList = new ArrayList<Boolean>();
resultsList.add(updateMainTabsAccess());
...
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
boolean res = true;
for (Boolean singleResult : resultsList) {
res = res && singleResult;
}
Here is the old style way to acheive your goal when Lambdas weren't introduced by Java 8.
public class TestMethodsListCall {
public abstract class Checker {
public abstract boolean check();
}
public static void main(String[] args) {
new TestMethodsListCall();
}
public TestMethodsListCall() {
final TestMethodsListCall that = this;
List<Checker> checkers = Arrays.asList( //
new Checker() { public boolean check() { return that.methodA(); } }, //
new Checker() { public boolean check() { return that.methodB(); } } //
// , ...
);
boolean res = true;
for (Checker c : checkers) {
res = res & c.check();
if (!res) {
// Break, display some message or all together
}
}
}
public boolean methodA() {
return true;
}
public boolean methodB() {
return false;
}
}

Determine the datatype of an Object's property

I have two similar object in Java / Groovy, lets say:
class a {
Date creation
}
class a {
String creation
}
and in my program, there is a switch that determines what object should I use (Groovy code):
def obj
if(/* certain criteria for a */) {
obj = new package.foo.a()
// ...
// Or some other process aside from initialization.
}
else if(/* certain criteria for the another a */) {
obj = new package.bar.a()
// ...
// Or some other process aside from initialization.
}
else {
obj = null
}
Later in the code, I need to determine the process I should perform based on the type of the property creation:
if(obj.creation instanceof Date) {
obj.creation = new Date()
}
else if(obj.creation instanceof String) {
obj.creation = '1995-08-17'
}
The above code doesn't work. Is there someway to do this? Of course I can always do the following if the property's datatype is not obtainable:
if(obj instanceof package.foo.a) {
obj.creation = new Date()
}
else if(obj instanceof package.bar.a) {
obj.creation = '1995-08-17'
}
You could try getting the class of the object and checking if it has the same class as whichever type you are checking for:
if(obj.creation.getClass().equals(Date.class)) {
obj.creation = new Date();
}
else if(obj.creation.getClass().equals(String.class)) {
obj.creation = "1995-08-17";
}
Sometimes depending on an object's type in necessary, but it should be avoided because it makes the code more fragile. You could end up with type checking littered all over your code base. In your case, you can delegate the class-specific behaviour to the class itself. Here's an example:
class A {
Date creation
void initializeCreationDate() {
creation = new Date()
}
}
/* I'm using a different class name to make this
* example self-contained.
*/
class B {
String creation
void initializeCreationDate() {
creation = '1995-08-17'
}
}
def obj
def condition = true
if(condition) {
obj = new A()
} else {
obj = new B()
}
obj.initializeCreationDate()
In the example, the two classes become responsible for setting their own creation date. This helps keep the code nice and neat.
Using a mixin instead
You can still achieve the same effect even when you're unable to (or do not want to) modify the source code of the two classes. In such a case, you can use a mixin to add the initializeCreationDate() method. Like this:
class A {
Date creation
}
/* I'm using a different class name to make this
* example self-contained.
*/
class B {
String creation
}
class DateInitializer {
static void initializeCreationDate(A object) {
object.creation = new Date()
}
static void initializeCreationDate(B object) {
object.creation = '1995-08-17'
}
}
def obj
def condition = true
if(condition) {
obj = new A()
} else {
obj = new B()
}
obj.metaClass.mixin DateInitializer
obj.initializeCreationDate()
It doesn't work because creation is null. null is not an instance of any objects.
You have to use reflection API to get a field type and then use Class.isAssignableFrom() to check type.
if(String.class.isAssignableFrom(a.class.getDeclaredField("creation").getType()){
...
}
I edited it to make the code compiles :)

How I can empty values get and set together in java?

I have get and set class :
public static class Structure{
private String YOne = null;
private String YTwo = null;
public String getYOne() {
return YOne;
}
public void setYOne(String YOne) {
this.YOne = YOne;
}
public String getYTwo() {
return YTwo;
}
public void setYTwo(String YTwo) {
this.YTwo = YTwo;
}
}
Then I fill that in my class :
Structure.setYOne("my value");
Structure.setYTwo("my value");
How I can empty all of them ?
Notice : I don't like empty that one by one .
You can implement a method in your Structure class that sets all the fields to null using Reflection:
public void clearFields() throws IllegalArgumentException, IllegalAccessException {
Field[] properties = this.getClass().getDeclaredFields();
for (Field f : properties) {
f.setAccessible(true);
f.set(this, null);
}
}
Rebuild your object, no other choice if you don't want to do it one by one
Structure s = new Structure();
// YOne and YTwo are null
s.setYOne("my value");
s.setYTwo("my value");
// YOne and YTwo are not null;
s = new Structure();
// YOne and YTwo are null again
edit : be careful though, it could mess up your reference if your object is used in another class.
You are lacking basic class and object concept here. You need to create an array of objects of Structure class. The use a foor loop to loop through all the objects and set methods.
for(Structure x : your_array_of_Structures ){
x.set(whatever);
x.get(whatever);
}
Go to http://www.tutorialspoint.com/java/java_loop_control.htm where you can get more tutorials on how to do these basic things in Java.

Categories

Resources