I want to use inst in another class SubscribeTables() I need it with all of its data. I tried to make a getter in Main() but it didnt work. Maybe i can pass it to another class somehow? Can someone help me with it?
Lets say i need to call inst.isConnected() in SubscribeTables()
public class Main {
public static void main(String[] args) throws IOException {
// Setup NT4 Client
NetworkTableInstance inst = NetworkTableInstance.getDefault();
inst.startClient4("FRC Stat Track");
selectNetworkTablesIP(inst, 5883);
// Connects after ~100ms
new SubscribeTables();
}
So to consolidate, in terms of code, your SubscribeTables class should look like this:
public class SubscribeTables {
private NetworkTableInstance instance;
// Make a constructor to take NetworkTableInstance
public SubscribeTables(NetworkTableInstance instance) {
this.instance = instance;
}
public void function() {
// Use the NetworkTableInstance for every function in this Class
boolean isConnected = instance.isConnected();
}
}
And the way to create a SubscribeTables object:
SubscribeTables tables = new SubscribeTables(inst);
The scope of NetworkTableInstance inst is limited to the lifecycle of main method as your new class is not aware. You have 2 options if you still want to do it in this way - but not recommened.
Pass the instance of NetworkTableInstance as a constructor paramater to SubscribeTables
Pass the instance of NetworkTableInstance to the respective methods as a method parameter you need to call on SubscribeTables
You can supply link of object A(type NetworkTableInstance) to object B(type SubscribeTables) either by argument in constructor or by argument in setter method. In both cases SubscribeTables class should have field of type NetworkTableInstance to put NetworkTableInstance object from constructor or setter arguments into the field.
Related
I'm trying to instantiate the constructor of a class which I imported as a Maven dependency via it's coordinates. The problem I have is that the particular constructor of this class, is invisible to me because it has no access modifier associated with it so it is default, meaning I can't access it from outside.
I know there is a way to access private methods via reflections, using getDeclaredMethod() method of class Method, but this doesn't work for constructors (please correct me if I'm wrong).
The class I'm trying to use is here:
public class DecisionTableBuilder {
// Notice no access modifier here so it's package-default
DecisionTableBuilder(Log log, File in, File out) {
some stuff ...
}
// public constructor
public DecisionTableBuilder() {}
// Method 1
public void compiler(File schema) {
some stuff ...
}
// Method 2
public void linker(File attribute) {
some stuff ...
}
}
Here is my toplevel in a separate project:
public class TopLevel {
public void testDecisionTableBuilder() {
// I get an error saying the constructor DecisionTableBuilder is not visible
DecisionTableBuilder builder = new DecisionTableBuilder();
// This works just fine, but no constructor...
DecisionTableBuilder builder2;
// This doesn't really work
Method[] m = DecisionTableBuilder.class.getDeclaredMethods("DecisionTableBuilder", "Log", "File", "File");
}
}
How can I access the Constructor and methods in a toplevel class which I created in a new project? Any assistance would be much appreciated
EDIT
public File graphDir;
public File outputDir;
public Log log;
Constructor<DecisionTableBuilder> constructor = DecisionTableBuilder.class.getDeclaredConstructor(Log.class,File.class,File.class);
constructor.setAccessible(true);
DecisionTableBuilder builder =constructor.newInstance(log, graphDir, outputDir);
Would this be correct?
You cannot access constructors with getDeclaredMethod or getDeclaredMethods. The Java reflection mechanism distinguishes between methods and constructors, and has separate methods for accessing them.
Try the getDeclaredConstructors method,
Constructor[] c = DecisionTableBuilder.class.getDeclaredConstructors();
or for a specific constructor, getDeclaredConstructor. Pass in the Class objects representing the parameter types, not the string names of the classes.
Constructor<DecisionTableBuilder> constructor =
DecisionTableBuilder.class.getDeclaredConstructor(Log.class, File.class, File.class);
You will want to set it accessible and then call newInstance to create a DecisionTableBuilder.'
constructor.setAccessible(true);
DecisionTableBuilder dtb = constructor.newInstance(yourLog, inFile, outFile);
You'll of course need to catch the several exceptions that these reflection calls can throw.
Suppose I have class:
MyObject b = new MyObject(){
private void method(){}
}
Is it possible to get method() by reflection? For toString I can write:
MyObject.class.getMethod("toString");
But what about for new created private method?
You have to invoke Object#getClass() on b reference to get the anonymous class, where the method is declared. MyObject.class will give you Class<MyObject>, which is not possibly what you want.
And then use Class#getDeclaredMethod() to get the private method:
Method method = b.getClass().getDeclaredMethod("method");
method.setAccessible(true);
method.invoke()
You can use it with:
Method method = b.getClass().getDeclaredMethod("method");
Here b.getClass() will return the class that the compiler generated for you for the anonymous inner class.
I can't easily imagine a situation in which that's a good approach, however.
Note that if you use a local named class, you don't even need to use reflection to call the method:
public class Test {
public static void main(String[] args) {
class Foo {
private void doSomething() {
System.out.println("Yes!");
}
};
Foo foo = new Foo();
foo.doSomething();
}
}
If you could give us more context about why you want this, we could probably be of more help in finding the best solution.
I'm loading a class with following statement:
Class classToLoad = Class.forName("com.somePackage.SomeotherPackage.classname" );
Later i wd use reflection to get the methods of this class. now for invoking the methods with methodname.invoke() function i'd require the object of the loaded class. thus i want to create the object of the loaded class. I try to do it this way:
Object obj = classToLoad.newInstance();
but the problem in this is that this way i don't get the object of the class loaded but i get object of Object class.
Now if i want to call the functions of the loaded class, i do it like:
methodName.invoke(obj);
it throws an exception:
java.lang.IllegalArgumentException: object is not an instance of declaring class
can anybody please help?
Update on the problem:
The problem is that i need the left hand side of the assignment to be of a different class type and that class type will be decided on run time
For the below statement:
Object instance = clazz.newInstance();
"instance" should be of the "clazz" type and not the "Object" class.
How can i achieve this?
It works fine when everything's set up correctly:
import java.lang.reflect.Method;
class Foo {
public Foo() {
}
public void sayHello() {
System.out.println("Hello");
}
}
public class Test {
public static void main (String[] args) throws Exception {
Class<?> clazz = Class.forName("Foo");
Method method = clazz.getMethod("sayHello");
Object instance = clazz.newInstance();
method.invoke(instance); // Prints Hello
}
}
My guess is that the method you've fetched (methodName) wasn't actually fetched from classToLoad.
You can also just cast the return type and invoke the method directly.
public class Foo{
void HelloReflection(){
System.out.println("Hello reflection");
}
public static void main(String[] args){
try{
Foo o = (Foo) Class.forName("Foo").newInstance();
o.HelloReflection();
}catch(Exception e){
e.printStackTrace();
}
}
}
java.lang.IllegalArgumentException: object is not an instance of declaring class
This can be thrown if the method has no arguments and not found in your object's class. Probably You are calling the invoke method on the wrong object or your fetched method is wrong for your object.
The problem is that i need the left hand side of the assignment to be of a different class type and that class type will be decided on run time. ... How can i achieve this?
Use some language other than Java. Java is statically typed, which basically means you're not allowed to do exactly what you just asked how to do. The other answers here correctly show how to invoke a method without knowing the type of an object at compile time, but you'll never be able to set the type of a variable at runtime.
At present I have a class that is calling the static method of a different class. What I am trying to do however is have the static method change a variable of the calling class, is that possible?
Example code:
public class exClass {
private int aVariable;
public exClass() {
othClass.aMethod();
}
}
public class othClass {
static void aMethod() {
// stuff happens, preferably stuff that
// allows me to change exClass.aVariable
}
}
So what I would like to know is, if there is a way to access aVariable of the instance of exClass that is calling othClass. Other than using a return statement, obviously.
Not if aClass doesn't expose that variable. This is what encapsulation and information hiding are about: if the designer of the class makes a variable private, then only the component that owns it can modify or access it.
Of course, the dirty little secret in Java is that reflection can get you around any private restriction.
But you should not resort to that. You should design your classes appropriately and respect the designs of others.
You can pass this as a parameter to the second function.
public class exClass {
public int aVariable;
public exClass()
{
othClass.aMethod(this);
}
}
public class othClass{
static void aMethod(exClass x)
{
x.aVariable = 0; //or call a setter if you want to keep the member private
}
}
you should gave the static method in othClass the instance of exClass like othClass.aMethod(this), then you can change the variable of that instance, or make the variable static if you dont need an instance
I am trying to access a form which is not static from another class which is also not static. I'd like to use a member in the class....
Public Class MainForm
public void setConsoleText(String Text){
jTextArea1.append(Text);
}
I need to know a way to reference this setter from my class "Log" which is basically where data goes to be parsed and logged. I want it to be like this:
private void consoleOut(String data) {
System.out.println(data);
MainForm.setConsoleText("data");
}
I cannot access this method.. I can only access MyForm.Class. Is there a way to reference the one that's been instantiated, or all of them in this virtual machine? It really doesn't matter as there will only be one of these running in this instance of the Java VM.
I just can't seem to figure this one out.
You need to give Log a non-static MainForm variable and pass reference to the currently visualized MainForm object into the Log class and into this variable. This can be done via a Log constructor parameter or via a setter method. Then you can call methods on this instance (but checking that it's not null first). Something like:
public class Log {
private MainForm mainForm; // our MainForm variable
public Log(MainForm mainForm) {
// setting the MainForm variable to the correct reference in its constructor
this.mainForm = mainForm;
}
private void consoleOut(String data) {
System.out.println(data);
if (mainForm != null) {
// now we can use the reference passed in.
mainForm.setConsoleText("data");
}
}
}
Edit 1
For instance if you create your MainForm object and display it from a main method somewhere, create Log along with it and pass the visualized MainForm into the Log constructor, something like so:
public static void main(String[] args) {
MainForm myMainForm = new MainForm();
// ... whatever code is necessary to set up the
// ... MainForm object so it can be visualized
myMainForm.setVisible(true); // and show it
Log myLogObject = new Log(myMainForm);
//...
}
Note that if this doesn't help you, you'll need to post more of your code.