I know there is, like, over 5 questions that ask this but mine is different. I am trying to get all classes in a package and run the tick function. Here is what one of my classes look like:
package com.stupidrepo.mydirectory.yayay;
public class test {
public void tick(MinecraftClient client) {
System.out.println(client.player.getName());
}
}
Here is how I am attempting to call this function:
ScanResult scanResult = new ClassGraph().acceptPackages("com.stupidrepo.mydirectory.yayay").enableClassInfo().scan();
private void doIt(MinecraftClient client) {
scanResult.getAllClasses().forEach((classInfo -> {
// System.out.println(classInfo.getName());
try {
classInfo.loadClass().getMethod("tick", MinecraftClient.class).invoke(null, client);
} catch (Exception e) {
e.printStackTrace();
}
}));
}
When I call the doIt function, it keeps giving me the java.lang.NoSuchMethodException error. When I print classInfo.getMethods();, it shows me [public void com.stupidrepo.mydirectory.yayay.test.tick(net.minecraft.client.MinecraftClient)].
So the method is there but java says it isn't. Please help! (By the way the code is for a Fabric MC mod)
The method tick is not static. But, when you are invoking method, you are not giving instance (but null), so it try to run the method as static. Such as It's not static, it failed.
To fix it, you can:
Set your method as static, for example:
package com.stupidrepo.mydirectory.yayay;
public class test {
public static void tick(MinecraftClient client) {
System.out.println(client.player.getName());
}
}
Create a new instance like that:
try {
Class<?> clzz = classInfo.loadClass(); // get class
Object obj = clzz.getConstructor().newInstance(); // create instance
clzz.getMethod("tick", MinecraftClient.class).invoke(obj, client); // get and call method
} catch (Exception e) {
e.printStackTrace();
}
Related
Okay so I have a bit a conundrum. I have a Qaurtz Cron that I want to use to schedule and run some Java Tests. These task are scheduled through a gui that Uses JavaFX. However, the job itself calls a run tests method. The job forces me to make certain elements static, but by making them static, I get a null pointer exception. I would really appreciate some help here.
So here is the job class that forces things to be static.
public class newJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("We are attempting the job now");
try {
FXMLDocumentController.runScheduledTests();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Inside my controller I have something like this:
public static void runTests() throws SQLException, IOException {
// Set running to true. In current form we do not use this bool,
// however, we may
// make changes that rely on this.
running = true;
FileOutputStream fos = null;
// Verify that users exist, and there is a url with the word max in it
int count = DBHelpers.getResults("SELECT * FROM USERS;", new String[] { "ID" }).length();
// Verify that we have both users and a maximo url to work with.
if ((!userList.isEmpty() || count > 0) && userMaxListChoice.length() > 5) {
// Set the proper driver, default to chrome if none is selected
if (IEbutton.isSelected()) {
BrowserConfig.setDriver(Browsers.IE());
} else {
BrowserConfig.setDriver(Browsers.Chrome());
}
// Let's assign maximo. If no one has clicked the use UserList
// button, assume that the data inside
// maximo name is good to use
if (userMaxListChoice != null) {
BrowserConfig.setMaximo(userMaxListChoice);
// System.out.println("used maxLIst choice");
} else {
// If the user has not selected a name from the maximo list,
// let's grab whatever
// they have entered in the maximoName field.
BrowserConfig.setMaximo(maximoName.getText());
}
// Set the system pause based on the interval string
int pause = Integer.parseInt(interval.getText().toString());
// Make sure the puase is in miliseconds
pause = pause * 1000;
BrowserConfig.setInterval(pause);
Note that the runScheduledTests() methods does some configuring and calls the runTest method. Inside the run test method is where I'm hitting the error specifically this line:
if (IEbutton.isSelected()) {
BrowserConfig.setDriver(Browsers.IE());
} else {
BrowserConfig.setDriver(Browsers.Chrome());
}
The reason is that above I have this :
#FXML
public static RadioButton ChromeButton;
#FXML
public static RadioButton IEbutton;
As I said this is a bit of an issue, If I don't make them static the job class yells at me for making a non-static reference.
How can I resolve this conflict?
TL;DR : You shouldn't use static on the fields annotated with #FXML.
For more information go through - javafx 8 compatibility issues - FXML static fields
You could load the FXML by using the FXMLLoader and then get an instance of the controller from it. By doing this, you can convert the method runScheduledTests() into a non-static method.
public class newJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
try {
FXMLLoader fxmlLoader =
new FXMLLoader(getClass().getResource("path-to-fxml.fxml"));
fxmlLoader.load();
FXMLDocumentController fxmlDocumentController =
(FXMLDocumentController)fxmlLoader.getController();
fxmlDocumentController.runScheduledTests(); // convert the method to non-static
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The problem is you are trying to use static when the controller itself is not static. Take into consideration I recommend taking a look at the difference between static and non-static here. In regards to fixing your code. First make your buttons ChromeButton and IEbutton not static. Then when your application class, something like this:
public class HelloWorld extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
//pass a reference of your stage to job.
}
}
Then Pass a reference of your buttons or controller into the Job class as a variable. Like this:
public class newJob implements Job{
private RadioButton chrome;
private RadioButton ie;
public newJob(RadioButton chrome, RadioButton ie) {
this.chrome = chrome;
this.ie = ie;
}
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("We are attempting the job now");
try {
FXMLDocumentController.runScheduledTests();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The core of your problem is controller variables CANNOT be static as the controller is dependent on instantiating the class and passing the required information in. The best way to fix this is by passing a reference either to the buttons or the class by using variables in the constructor. Please read the link I sent you to get a better understanding between static and non-static. Also, if you are confused about constructors take a look here as well.
how to get method return value isFailed along with exception details if method is failed
class sample
{
booelan isFailed=false;
boolean m1()
{
try{
logic of method
}
catch(Exception e)
{
String cause=e.getMessage();
isFailed=true;
}
return isFailed;
}
}
If the calling method needs to know about the Exception, just let it go through.
m1 doesn't have to return a boolean, it either worked or threw an Exception, so the calling method will know whether it is a success or not.
In this example, the calling method (m1Caller) is in the same class for simplicity .
class sample {
boolean isFailed = false;
void m1() throws Exception {
// logic of method
}
void m1Caller() {
try {
m1();
} catch (Exception e) {
// do whatever you want with the Exception's message
System.out.println(e.getMessage());
isFailed = true;
}
}
}
I'm not great with java terminology so it will be easier for you to understand via example:
I instantiate a mymethods class from a
Main class:
public class Main()
{
public boolean hasErrors = false;
MyMethods m = new MyMethods(); //cannot use try/catch
public static void main(String[] args){
m.writeToFile("text");
}
}
In the above class, i cannot (i tried) use a try catch to catch a manually thrown FileNotFoundException but apparently such methods cannot be used in that location (wrapping MyMethods m... in try/catch). I had tried to throw that error when my requisite file wasnt found
MyMethods:
public class MyMethods()
{
public MyMethods(){
if(!new File("file.txt").canWrite()){
changeSuper(true);
throw new FileNotFoundException();
}
}
public void changeSuper(boolean b) //does not work
{
super.hasErrors = b;
}
//input more methods etc here
}
Why is it not possible to use try/catch?
How can i report a filenotfound to the main method?
Note that this is from a GUI app in netbeans, but is not the focus here. Program will not compile if try/catch wraps that line
(note to admins/mods: this question needs butchering, but I cannot express my question better myself)
You just need to add the throws keyword to your method, i.e:
public static void myMethod() throws FileNotFoundException{
// Code goes here ...
if( fileNotFound )
throw new FileNotFoundException("File not found.");
}
you can then catch the exception by surrounding your call to the method with a try/catch block:
try {
// Do stuff...
myMethod();
} catch (FileNotFoundException ex){
// Handle error, if thrown...
}
Constructor and method not working as expected in Java program
I have the following code:
package principal;
public class Principal {
public static void main(String[] args) {
Thread filosofos[]=new Thread[5];
for (int i=0;i<5;i++) {
System.out.println("loop");
filosofos[i]=new Thread();
filosofos[i].start();
}
// TODO Auto-generated method stub
}
}
package principal;
public class Filosofo implements Runnable{
static final int tamanho=5;
static int talheres[]=new int[tamanho];
static Semaforo semaforo= new Semaforo(1);
static int quantidade=0;
int id;
public Filosofo(){
System.out.println("Construtor iniciado.");
for (int i=0;i<tamanho;i++) {
talheres[i]=0;
}
quantidade++;
id=quantidade;
}
public void run () {
System.out.println("Filosofo "+id+" iniciado");
try {
// Filosofo pensando
Thread.sleep(1000);
} catch (Exception e) {
}
semaforo.down();
System.out.println("Filosofo "+id+" comendo");
semaforo.up();
}
}
The program should exhibit the string "Construtor iniciado." and the other 2 strings of method run. However when I run the code nothing happens only output that I receive is
loop
loop
loop
loop
loop
why the string of the constructor is not showing up? Why the method run is not running as expected? It looks like the constructor and the method run are not running at all, and I don't know what is going wrong.
You have declared class Filosofo but you never create a single instance of it.
Perhaps you want to pass a new instance of Filosofo as thread constructor parameter for each thread?
package principal;
public class Principal
{
public static void main(String[] args)
{
Thread filosofos[]=new Thread[5];
for (int i=0;i<5;i++) {
filosofos[i]=new Thread(new Filosofo());
filosofos[i].start();
}
}
}
Except this, instead of using a static field for counting Filosofo instances and assign them an id, why you don't just pass the id in the constructor?
Also the other fields, don't need to be static, pass the shared fields, like semaforo, in the constructor and copy them in a class field.
I don't know the meaning of talheres field and I don't understand why you reinitialize a static field in each instance constructor, maybe you can just initialize once in main and pass that field in the constructor of each Filosofo, as you know, arrays are not copied, only a reference to them is copied.
Also instead of catch (Exception e) you should use catch (InterruptedException e).
You should do something useful with the exception, like printing it.
If you intend to ignore an exception at least you should add a very detailed comment on why you are doing that.
You never instantiate any Filosofo, just Threads.
How would one go about checking to see if a method exists for a class in Java? Would a try {...} catch {...} statement be good practice?
I assume that you want to check the method doSomething(String, Object).
You might try this:
boolean methodExists = false;
try {
obj.doSomething("", null);
methodExists = true;
} catch (NoSuchMethodError e) {
// ignore
}
This will not work, since the method will be resolved at compile-time.
You really need to use reflection for it. And if you have access to the source code of the method you want to call, it's even better to create an interface with the method you want to call.
[Update] The additional information is: There is an interface that may exist in two versions, an old one (without the wanted method) and a new one (with the wanted method). Based on that, I suggest the following:
package so7058621;
import java.lang.reflect.Method;
public class NetherHelper {
private static final Method getAllowedNether;
static {
Method m = null;
try {
m = World.class.getMethod("getAllowedNether");
} catch (Exception e) {
// doesn't matter
}
getAllowedNether = m;
}
/* Call this method instead from your code. */
public static boolean getAllowedNether(World world) {
if (getAllowedNether != null) {
try {
return ((Boolean) getAllowedNether.invoke(world)).booleanValue();
} catch (Exception e) {
// doesn't matter
}
}
return false;
}
interface World {
//boolean getAllowedNether();
}
public static void main(String[] args) {
System.out.println(getAllowedNether(new World() {
public boolean getAllowedNether() {
return true;
}
}));
}
}
This code tests whether the method getAllowedNether exists in the interface, so it doesn't matter whether the actual objects have the method or not.
If the method getAllowedNether must be called very often and you run into performance problems because of that, I will have to think of a more advanced answer. This one should be fine for now.
Reflection API throws NoSuchMethodException when using Class.getMethod(...) functions.
Otherwise Oracle has a nice tutorial about reflection http://download.oracle.com/javase/tutorial/reflect/index.html
In java this is called reflection. The API allows you to discover methods and call them at runtime. Here is a pointer to the docs. It's pretty verbose syntax but it'll get the job done:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
I would use a separate method to handle the exception and have a null check to check if method exists
Ex : if (null != getDeclaredMethod(obj, "getId", null)) do your stuff...
private Method getDeclaredMethod(Object obj, String name, Class<?>... parameterTypes) {
// TODO Auto-generated method stub
try {
return obj.getClass().getDeclaredMethod(name, parameterTypes);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
If you're using Spring in your project you may check ReflectionUtil.findMethod(..). It returns null if method does not exist or does not match your requirements. Documentation.
Roland Illig is correct, but wanted to add in an example of how to check if a method exists that requires a parameter using Class.getMethod. Can also use Class.getDeclaredMethod if you are trying to access a private method.
class World {
public void star(String str) {}
private void mars(String str) {}
}
try {
World.class.getMethod("star", String.class);
World.class.getDeclaredMethod("mars", String.class);
} catch (Exception e) {}
Other solution:
public static <O> boolean existsMethod(final String methodName, final O o) {
return Stream.of(o.getClass().getMethods()).map(Method::getName).anyMatch(methodName::equals);
}