Reflection on swing components - java

I'm trying to assign a value to a swing component through reflection. Let's use a JCheckBox for example. I have the following class:
public class JCheckBoxTest
{
private JCheckBox test;
public JCheckBoxTest()
{
this.test = new JCheckBox();
}
public reflectionTest()
{
Field field;
Method method;
field = this.getClass().getDeclaredField("test");
method = field.getType().getSuperclass().getDeclaredMethod("setSelected");
method.invoke(field, "true");
}
}
This code fails at:
method = field.getType().getSuperclass().getDeclaredMethod("setSelected");
because it cannot find the specified "setSelected" method since it is located inside the inner class "ToggleButtonModel" of the superclass "JToggleButton" which is extended by the "JCheckBox" class.
What would be the best approach to solve this?
Thanks.
Edit: Corrected typo in code.

Class#getMethod and Class#getDeclaredMethod both provide the means to supply the name of the method and optional parameters
JCheckBox#setSelected requires a boolean paramater, so you really should be using
method = field.getClass().getDeclaredMethod("setSelected", boolean.class);
But as you've noted, this is unlikely to work, instead, you could try
method = field.getClass().getMethod("setSelected", boolean.class);
Now, I've also had this fail to work as well, which is why I tend to use something like...
public static Method findMethod(Class parent, String name, Class... parameters) throws NoSuchMethodException {
Method method = null;
try {
method = parent.getDeclaredMethod(name, parameters);
} catch (NoSuchMethodException exp) {
try {
method = parent.getMethod(name, parameters);
} catch (NoSuchMethodException nsm) {
if (parent.getSuperclass() != null) {
method = findMethod(parent.getSuperclass(), name, parameters);
} else {
throw new NoSuchMethodException("Could not find " + name);
}
}
}
return method;
}
which is a little brute force.
So with that in mind...
JCheckBox cb = new JCheckBox();
try {
Method method = cb.getClass().getDeclaredMethod("setSelected", boolean.class);
System.out.println("1. " + method);
} catch (NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
}
try {
Method method = cb.getClass().getMethod("setSelected", boolean.class);
System.out.println("2. " + method);
} catch (NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
}
try {
Method method = findMethod(cb.getClass(), "setSelected", boolean.class);
System.out.println("3. " + method);
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
Which outputs something like...
java.lang.NoSuchMethodException: javax.swing.JCheckBox.setSelected(boolean)
2. public void javax.swing.AbstractButton.setSelected(boolean)
3. public void javax.swing.AbstractButton.setSelected(boolean)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at test.Test.main(Test.java:13)
Disclaimer
Reflection like this should be a last resort. It's slow and prone to code refactoring

Related

Java reflection error Java.lang.NoSuchMethodException, but method exists

I can't get to work java reflection in Spring boot with Controller and JdbcTemplate.
Default controller looks like:
public class DefaultController {
private static final Logger logger = LoggerFactory.getLogger(DefaultController.class);
public JsonResponseDataModel selectOneAuto(Long id, Class<?> repository, HttpServletResponse response){
final JsonResponseDataModel result = new JsonResponseDataModel();
System.out.println("The name of class is " + repository.getName());
Method[] methods = repository.getMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
}
try {
//Method method = repository.getClass().getMethod("selectOne", Long.class);
Method method = repository.getClass().getDeclaredMethod("selectOne", Long.class);
method.invoke(repository, id);
logger.info("selectOneAuto : id={} ", id);
} catch (EmptyResultDataAccessException e) {
result.setEmptyResultDataAccessException("id", id.toString());
} catch (DataAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}
}
Inside CompanyRepository class is defined selectOne method with Long input:
#Transactional(readOnly=true)
public CompanyModel selectOne(Long id) {
CompanyModel result = null;
final String sql = "SELECT * FROM company WHERE id=?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new CompanyRowMapper());
}
When I create a new class "CompanyController extends DefaultController" and call method selectOneAuto:
selectOneAuto(id, new CompanyRepository().getClass(), response);
Then it ends with error on line "Method method = repository.getClass().getDeclaredMethod("selectOne", Long.class);"
"Java.lang.NoSuchMethodException: java.lang.Class.selectOne(java.lang.Long)"
But the for loop inside "selectOneAuto" method outputs method named "selectOne". What is wrong here?
Your code attempts to call the method on an instance of Class.
method.invoke(repository, id);
repository object is an instance of Class since you are passing new CompanyRepository().getClass() as parameter.
The second point to be noted is repository is an instance of Class already so there is no need to call getClass() on this object.
You should obtain the method object using the following code :
Method method = repository.getDeclaredMethod("selectOne", Long.class);
And then this should work :
CompanyRepository repsitoryObj = new CompanyRepository();
method.invoke(repsitoryObj, id);
Or a better and cleaner way is to simply change the type of your repository parameter as CompanyRepository your method will look as follows:
public JsonResponseDataModel selectOneAuto(Long id, CompanyRepository repository, HttpServletResponse response){
final JsonResponseDataModel result = new JsonResponseDataModel();
System.out.println("The name of class is " + repository.getClass().getName());
Method[] methods = repository.getClass().getMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
}
try {
//Method method = repository.getClass().getMethod("selectOne", Long.class);
Method method = repository.getClass().getDeclaredMethod("selectOne", Long.class);
method.invoke(repository, id);
logger.info("selectOneAuto : id={} ", id);
} catch (EmptyResultDataAccessException e) {
result.setEmptyResultDataAccessException("id", id.toString());
} catch (DataAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}

Java re-throw Exception

I have a Project with two classes. One Object class and one GUI class.
I would like to throw my own declared Exception if an error occurs.
I have two methods:
public class getValueClass {
private List<Value> liste;
public List<Value> getValues() {
try {
liste = this.getVal();
} catch (ValueException ex) {
System.out.println("EXCEPTION!! " + ex.getMessage());
ex.printStackTrace();
}
return liste;
}
public List<Value> getVal() throws ValueException
{
liste = null;
try {
// initialize list
// do some stuff
//test exception
if(1 == 1)
{
throw new Exception();
}
} catch (Exception ex) {
throw new ValueException("QWE " + ex);
}
return liste;
}
}
Now the exception is thrown and I catch the exception in my getValues Method and print the Message/Stack
But I call the Method getValues in my GUI-Class and I want to catch the Exception there and print some Information in my dialog!
GUI:
public void myMethod()
{
try
{
l = cs.getValues();
}
catch(Exception ex)
{
System.out.println("TEST " + ex.getMessage());
}
}
But I don't get there because I already catch it in the getValues() method.
Is it possible to make it like this WITHOUT adding throws at method declaration for getValues() method? ( I get this method from an interface and will not change it)
You could throw an unchecked RuntimeException such as IllegalArgumentException or customized RuntimeException subclass.
public List<Value> getValues() {
try {
liste = this.getVal();
} catch (ValueException ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
return liste;
}
There is a way to do what you want, but I advise against it depending on your intended purpose of ValueException, as it could be the source of future bugs
You can have ValueException extend RuntimeException. The RuntimeException set of exceptions, as the name implies, are thrown at runtime and are not declared at compile time, and need to be explicitly caught. This way you wouldn't have to add a throws declaration to the getValues() method, but would still catch it in your main method.
Disclaimer explained:
The reason I am not a fan of this idea (and RuntimeExceptions in general) is because they're uncaught until explicitly looked for. This in my mind doesn't make for easy-to-use code, and while it has it's very handy uses, I don't feel right using them because of the uncertainty they carry
Again, this is my opinion, not Java's

Count traffic separately for each SIM on 2SIM MTK-based phone

Any app I could find on GPlay counts traffic for both SIM while in Settings-Data Usage traffic is counted for each SIM. I used jd-gui to see how it's done and have found that classes from private API were used.
import android.net.INetworkStatsService;
import android.net.INetworkStatsService.Stub;
import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
import android.net.NetworkStatsHistory;
import android.net.NetworkStatsHistory.Entry;
import android.net.NetworkTemplate;
Can I use reflection to use them?
Update.
I've tried to use Reflection. Executing this code give me an exception "java.lang.InstantiationException: can't instantiate class android.net.INetworkStatsService"
Class<Object> MyINetworkStatsService = null;
try {
MyINetworkStatsService = (Class<Object>) Class.forName("android.net.INetworkStatsService");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object mStatsService = null;
try {
mStatsService = MyINetworkStatsService != null ? MyINetworkStatsService.newInstance() : null;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Upd. Because both StatsService and StatsSession are interfaces, I can't instantiate them and should use Proxy. Can anyone help with that?
Upd. I've made an effort
String id = getActiveSubscriberId(mContext);
try {
Object tmpl = null;
long stats = 0;
Class<?> a = Class.forName("android.net.NetworkTemplate");
Class<?> b = Class.forName("android.net.INetworkStatsService");
Method getState = b.getMethod("getNetworkTotalBytes", a, long.class, long.class);
Method[] am = a.getDeclaredMethods();
Method getTemplate = null;
for (Method m : am) {
if (m.getName().equalsIgnoreCase("buildTemplateMobileAll")) {
getTemplate = m;
break;
}
}
if (getTemplate != null) {
getTemplate.setAccessible(true);
tmpl = getTemplate.invoke(a.getClass(), id);
}
Object object = Proxy.newProxyInstance(b.getClass().getClassLoader(), b.getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getNetworkTotalBytes")) {
return method.invoke(args[0], args[1], args[2], args[3]);
}
throw new RuntimeException("no method found");
}
});
Object[] args = {b.getClass(), tmpl, Long.MIN_VALUE, Long.MAX_VALUE};
stats = (long) ((b.getClass()) object).getState(args);
} catch (ClassNotFoundException e0) {
} catch (NoSuchMethodException e0) {
} catch (IllegalAccessException e0) {
} catch (InvocationTargetException e0) {
}
But it says that there is an error "Method call expected" in
stats = (long) ((b.getClass()) object).getState(args);
If I change this string like this
stats = (long) ((b) object).getState(args);
I get another error - "Unknown class: 'b'"

Java Generic Method to Instantiate any Class with any Constructor using Reflection

As we know Java uses erasure, so any Generic class cannot do
T t = new T();
So I was trying out Java reflection to have a class with Static methods, to instantiate any Class with any Constructor. Here is the code.
import java.lang.reflect.*;
public class GenericNewInstance {
public static <T> T createInstance(Class<T> cObj) {
try {
return cObj.newInstance();
} catch (InstantiationException e) {
System.out.println("Instantiation Exception");
return null;
} catch (IllegalAccessException e) {
System.out.println("Illegal Access Exception");
return null;
}
}
public static <T> T createInstanceUsingRelection(Class<T> c, Object... initArgs) {
Constructor<T> cTor = null;
Class<?>[] cObjs = new Class<?>[initArgs.length];
int i = 0;
for(Object o : initArgs) {
cObjs[i++] = o.getClass();
}
try {
cTor = c.getConstructor(cObjs);
} catch (SecurityException e) {
System.out.println("security exception. Cannot get Constructor");
return null;
} catch (NoSuchMethodException e) {
System.out.println("NoSuchMethodException Cannot get constructor");
return null;
}
try {
return cTor.newInstance(initArgs);
} catch (IllegalArgumentException e) {
System.out.println("Illegal Argument Exception");
return null;
} catch (InstantiationException e) {
System.out.println("Instantiation Exception");
return null;
} catch (IllegalAccessException e) {
System.out.println("Illegal Access Exception");
return null;
} catch (InvocationTargetException e) {
System.out.println("Invocation Target Exception");
return null;
}
}
}
Example for using this.
Integer i = GenericNewInstance.createInstanceUsingRelection(Integer.class, "0");
So my questions:
Is this the right way to implement it? (or is it verbose?)
What are the typical use cases of doing this?
Can/Should we avoid using Reflection while using Generics?
Your code will fail at c.getConstructor(cObjs) since this doesn't take into account the type hierarchy. If any argument is a subtype of the constructor's declared param type, this call will not return it. You'll need quite a lot more type juggling to get it working. I advise you to take a look at the code that already solves this problem. Perhaps you can even use that library as-is, your choice. It's the implementation code for Clojure, a JVM-based dynamic language that needs exactly this stuff. The library is available from the Maven central repo.
BTW Your exception handling is redundant. Either just declare throws Exception or catch any Exception and wrap it in a RuntimeException. When something fails, the original exception is the best diagnostic.

In Java, how to use reflection to get a static method and execute it? [duplicate]

This question already has answers here:
How do I invoke a private static method using reflection (Java)?
(5 answers)
Closed 8 years ago.
I have a bunch of static method names, how do I execute them. I think I can use reflection, but how to do that?
directly from the interwebz
Class<?> class1;
try {
class1 = Class.forName(CLASS);
Method method = class1.getMethod(METHOD, String.class);
Object o = method.invoke(null, NAME);
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Code to execute static method:
Method method = Utils.class.getMethod("generateCacheFolderName", Integer.class);
System.out.println(method.invoke(null, new Integer(10)));
and class with static method:
public class Utils {
public static String generateCacheFolderName(Integer len) {
Random rand = new Random();
StringBuilder sb = new StringBuilder(len);
for(int i = 0; i<len; ++i)
sb.append(rand.nextInt() % 10);
return sb.toString();
}
public static String anotherStaticMethod() {
return null;
}
}
static public Object execute( Class<?> cls, Object instance, String methodname,
Object[] args, Class<?>[] types ) throws Exception {
Object result = null;
Method met = cls.getMethod( methodname, types );
if (instance == null && !Modifier.isStatic( met.getModifiers() )) {
throw new Exception("Method '" + methodname + "' is not static, so "
+ "instance must be not null");
}
try {
result = met.invoke( instance, args );
}
catch (InvocationTargetException ite) {
throw (Exception) ite.getCause();
}
return result;
}

Categories

Resources