Can I access the static variables of the 'Class' Object? - java

Having this method:
readAllTypes(Class clazz) {...}
Can I access the static variables of the class?

Yes. Just use Class.getDeclaredFields() (or Class.getDeclaredField(String)) as normal, and to get the values, use the Field.getXyz() methods, passing in null for the obj parameter.
Sample code:
import java.lang.reflect.Field;
class Foo {
public static int bar;
}
class Test {
public static void main(String[] args)
throws IllegalAccessException, NoSuchFieldException {
Field field = Foo.class.getDeclaredField("bar");
System.out.println(field.getInt(null)); // 0
Foo.bar = 10;
System.out.println(field.getInt(null)); // 10
}
}

You can find the field using clazz.getDeclaredFields(), which returns a Field[], or by directly getting the field by name, with clazz.getDeclaredField("myFieldName"). This may throw a NoSuchFieldException.
Once you've done that, you can get the value of the field with field.get(null) if the field represents an object, or with field.getInt(null), field.getDouble(null), etc. if it's a primitive. To check the type of the field, use the getType or getGenericType. These may throw an IllegalAccessException if they're not public, in which case you can use field.setAccessible(true) first. You can also set the fields in the same way if you just replace "get" with "set".

Related

Access enum name through reflection

I am trying to access the name of an enum through reflection (the name field of the Enum class) but I get a NoSuchFieldException.
See below a simple example: the program prints 5 for the Integer but throws an Exception for the enum.
Is there an elegant way to get the inspect method to work for enums?
public class Test {
static enum A {
A;
}
public static void main(String[] args) throws Exception {
Integer i = 5;
System.out.println(inspect(i, "value")); // prints 5, good
A a = A.A;
System.out.println(inspect(a, "name")); // Exception :-(
}
private static Object inspect(Object o, String fieldName) throws Exception {
Field f = o.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(o);
}
}
getField or getDeclaredField methods will only return positive results for fields declared in called class. They will not search for fields declared in superclasses. So, to get the refference for name field, you'll need to go deeper. Get the superclass reference (which in your case will be Enum class) and search for name field there.
o.getClass().getSuperclass().getDeclaredField(fieldName);

Why doesn't calling a static variable chained from a static method that returns null throw a NPE?

I have the following code
public class Test {
static String mountain = "Everest";
static Test favorite() {
System.out.print("Mount ");
return null;
}
public static void main(String[] args) {
System.out.println(favorite().mountain);
}
}
I thought it would raise a NPE but it is giving Mount Everest as output can anyone clarify?
It just so happens that you can access static members on object references. In that case, the member is resolved according to the type of the reference, not its value.
The Java Language Specification says this about field access of static members
If the field is a non-blank final field, then the result is the value
of the specified class variable in the class or interface that is the
type of the Primary expression.
If the field is not final, or is a blank final and the field access
occurs in a constructor, then the result is a variable, namely, the
specified class variable in the class that is the type of the Primary
expression.
So the Primary, the instance, does not matter.
When you access a static member on an instance of a class, the Java compiler completely ignores the runtime value (and even class) of the variable and uses the member belonging to the declared class. In this case, your code is equivalent to:
favorite();
System.out.println(Test.mountain);
Even if you had code like this:
public class SubTest extends Test {
static String mountain = "Kilimanjaro";
}
...
Test foo = new SubTest();
System.out.println(foo.mountain);
you'll still get the value on the Test class.
favorite() is a static method that returns Test type. Then you use the static variable of this class (mountain). This all works as you never use (and do not need to use) an instance of this class so there can be no null pointer exception.

Using reflection get a static private hashmap in java

I'm trying to find a way to extract a HashMap from a private static field within another class via Java.
eg.
Inside FooClass there is a static field that looks like this:
private Map entityRenderMap;
Then in its construct it has:
entityRenderMap = new HashMap();
How do you get the values within entityRenderMap via Reflection in Java? I've tried this but get errors:
cl = RenderManager.class.getDeclaredField("entityRenderMap");
cl.setAccessible(true);
Object foo = cl.get(this.entityRenderMap);
Mod.log(cl.getName());
The error I get is:
java.lang.IllegalArgumentException: Can not set java.util.Map field RenderManager.entityRenderMap to java.util.HashMap
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(Unknown Source
First, your code doesn't match your explanation. Is it really a static field or is it not (your code says it's not)?
If it is static, you should pass null as argument to cl.get() (you don't need an instance to access static members).
However, I suspect that your field is actually not static, and your passing the wrong instance to cl.get(). The JavaDocs to Field.get() state it would throw an IllegalArgumentException in this case. You need to pass a RenderManager instance to this method. Your code looks like your passing a Map (the entityRenderMap).
And last, is this code inside your RenderManager class? I suspect this, because your accessing a field with this with the same name as the field you want to set. In this case, don't use reflection at all!
Are you certain it is a static field. The javadoc of the get method clearly states:
If the underlying field is a static field, the obj argument is ignored; it may be null.
Otherwise, the underlying field is an instance field. If the specified obj argument is null, the method throws a NullPointerException. If the specified object is not an instance of the class or interface declaring the underlying field, the method throws an IllegalArgumentException.
So with a static field you would not get the IllegalArgumentException since the parameter is ignored. Further, the code you posted shows it is not a static field but a regular field (since it lacks the word static, and its initialized in the constructor).
If you want to access the field of a certain instance A, you should pass that instance A to the Field#get method, and not the A.field as you are trying to do with your cl.get(this.entityRenderMap) call.
You can take a look at this tutorial for some examples
If the field is really static, you should pass null as an argument to cl.get().
If the field is not static, then you must pass the instance of FooClass which you want to get the field value from:
FooClass fc = new FooClass(); // or whatever, provided that fc is a FooClass instance
Object foo = cl.get(fc);
I'm assuming cl is a java.lang.reflect.Field. The documentation states that Fields' get-method will throw:
IllegalArgumentException - if the specified object is not an instance
of the class or interface declaring the underlying field (or a
subclass or implementor thereof).
You should be passing the RenderManager-object to the get-method instead of the field (unless it's static, which it is not according to your example).
vim Test.java
import java.util.*;
import com.dp4j.*;
class FooClass{
private static Map entityRenderMap;
FooClass(){
entityRenderMap = new HashMap();
}
}
public class Test{
#Reflect
public static void main(String... args){
Map reflectEntityMap = FooClass.entityRenderMap;
}
}
javac -cp ~/ws/dp4j/dp4j.jar -Averbose=true Test.java
Test.java:16: Note:
import java.util.*;
import com.dp4j.*;
class FooClass {
private static Map entityRenderMap;
FooClass() {
entityRenderMap = new HashMap();
}
}
public class Test {
public Test() {
super();
}
#Reflect()
public static void main(String... args) throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalArgumentException, java.lang.IllegalAccessException {
java.lang.reflect.Field entityRenderMapField = null;
entityRenderMapField = Class.forName("FooClass").getDeclaredField("entityRenderMap");
entityRenderMapField.setAccessible(true);
Map reflectEntityMap;
reflectEntityMap = (.java.util.Map)entityRenderMapField.get("");
}
}

Getting value of public static final field/property of a class in Java via reflection

Say I have a class:
public class R {
public static final int _1st = 0x334455;
}
How can I get the value of the "_1st" via reflection?
First retrieve the field property of the class, then you can retrieve the value. If you know the type you can use one of the get methods with null (for static fields only, in fact with a static field the argument passed to the get method is ignored entirely). Otherwise you can use getType and write an appropriate switch as below:
Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
System.out.println(f.getInt(null));
}else if(t == double.class){
System.out.println(f.getDouble(null));
}...
R.class.getField("_1st").get(null);
Exception handling is left as an exercise for the reader.
Basically you get the field like any other via reflection, but when you call the get method you pass in a null since there is no instance to act on.
This works for all static fields, regardless of their being final. If the field is not public, you need to call setAccessible(true) on it first, and of course the SecurityManager has to allow all of this.
I was following the same route (looking through the generated R class) and then I had this awful feeling it was probably a function in the Resources class. I was right.
Found this:
Resources::getIdentifier
Thought it might save people some time. Although they say its discouraged in the docs, which is not too surprising.
I was looking for how to get a private static field and landed here.
For fellow searchers, here is how:
public class R {
private static final int _1st = 0x334455;
}
class ReflectionHacking {
public static main(String[] args) {
Field field = R.class.getFieldDeclaration("_1st");
field.setAccessible(true);
int privateHidenInt = (Integer)field.get(null);
}
}

How do I create a constant object in Java?

How do I create a reference to a constant object?
final Myclass obj = new Myclass();
does not work, it says obj(the reference) should not be re-assigned but we can still change the object referred. I want to ensure that the object itself does not change once constructed.
Just make it immutable (like String is). Or wrap it in another object which restricts access to mutators of the object in question (like Collections.unmodifiableList() and consorts do).
You are mixing two things: final and immutable.
A variable can be final, so you can't change it's a value (or object reference) after it is initialized (but of course you can change the reference's objects attributes)
An object can be immutable (not a keyword but a property), so you can't change it's value after it is created. The string is a good example - you can not change the backing char[] inside a String object.
What you want is an Immutable Object. There are no keywords in Java that can instantly make an object immutable. You have to design the object's logic, so that its state cannot be changed. As BalusC put, you can wrap it in another object which restricts access to its mutators.
I don't think there's any built in keyword to make that possible in Java. Even if the reference is constant/final, the internals of the object could still be changed.
Your best options is to have a ReadOnly implementation version of your class.
You can read more about this here: http://en.wikipedia.org/wiki/Const-correctness#final_in_Java
In Java, an immutable class is generally means that it doesn't have "setters" and any field that can be accessed with a "getter" should also be immutable. In order to get your data into the class to start, you'll need to have a constructor that takes the values as arguments:
public class MyClass {
String something;
int somethingElse;
// The class can only be modified by the constructor
public MyClass(String something, int somethingElse) {
this.something = something;
this.somethingElse = somethingElse;
}
// Access "something". Note that it is a String, which is immutable.
public String getSomething() {
return something;
}
// Access "somethingElse". Note that it is an int, which is immutable.
public int getSomethingElse() {
return somethingElse;
}
}
Yes it does you seem to have forgotten to set the type.
final MyClass obj = new Myclass();
That means that obj can only be assigned once. Java does not have a const keyword like C++ does. If MyClass is not declared final (final class MyClass { ... }) it can still change.
final variables should be assigned in the moment of declaration.
final MyClass obj = new MyClass();
In java object constant means you cannot change its reference but you can change the values of its state variables untill they are not final. if all the member variables are final then its a perfect constant, where you cannot change anything.
Here is a way to wrap any object to make it "roughly" immutable.
All method calls that are not 'getters' will throw an Exception. This code defines a getter as a method that meets these criteria:
name of the method starts with get or is
it takes no arguments
it returns a value (not void return type)
Yes, getter methods could mutate an object. But if your code (or code you are using) is doing that, you have some bigger problems, please go get some help :)
the code:
class ImmutableWrapper
public static <T> T wrap(T thing) {
return (T) Proxy.newProxyInstance(thing.getClass().getClassLoader(), new Class[]{thing.getClass()}, OnlyGettersInvocationHandler.instance);
}
private static class OnlyGettersInvocationHandler implements InvocationHandler {
public static InvocationHandler instance;
#Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String name = method.getName();
if ((args == null || args.length == 0)
&& (name.startsWith("get") || name.startsWith("is")
&& !method.getReturnType().equals(Void.class))) {
return method.invoke(proxy, args);
} else {
throw new UnsupportedOperationException("immutable object: " + proxy + ", cannot call " + name);
}
}
}
}
SomeClass myThing = ... create and populate some object ...
SomeClass myImmutableThing = ImmutableWrapper.wrap(myThing);
myImmutableThing.setValue('foo'); // throws Exception
myImmutableThing.whatever(); // throws Exception
myImmutableThing.getSomething(); // returns something
myImmutableThing.isHappy(); // returns something
Mayby you can create class with final attributes. So, you can't change it: object == const.
At least "String" immutable because of it:
public final class String implements Serializable, Comparable<String>, CharSequence {
private final char[] value;
//...
}

Categories

Resources