I have the following classes:
public class A {
static {
B.load(A.class);
}
public static final C field1 = new C("key1", "value1");
public static final C field2 = new C("key2", "value2");
public static void main(String[] args) {
System.out.println(A.field1);
}
}
and
public class B {
public static void load(Class<?> clazz) {
for (Field field : clazz.getFields()) {
try {
System.out.println("B.load -> field is " + field.get(null));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
and
public class C {
private final String key;
private final String value;
public C(String key, String value) {
super();
this.key = key;
this.value = value;
}
public String getKey() {
return this.key;
}
public String getValue() {
return this.value;
}
#Override
public String toString() {
return "C [key=" + this.key + ", value=" + this.value + "]";
}
}
When A is executed I get:
B.load -> field is null
B.load -> field is null
C [key=key1, value=value1]
Why does field.get(null) return a null value when it is executed? I get no exception and it seems that this behavior is not explained by the Javadoc.
I believe all static members will be executed (for static blocks) and initialized (for static fields) in declaration order. Try placing the static block of class A at the end of the class, or at least after the static fields. Lemme know if that makes a difference.
EDIT: info regarding the behaviour for primitives and Strings...
When you have a final static field that is a primitive or a String literal (or an expression that can be statically evaluated that results in one of these), it's considered a compile-time constant. Basically, setting such a value does not require "computation", like invoking a constructor or evaluating vis-a-vis other fields that may not have been initialized yet. Although Strings aren't primitives, they're given a special treatment in compilation to make String literals in code a possibility.
This means such fields can be assigned as soon as a class has been loaded and is ready for initialization. Although I don't know the specification details regarding that, experimenting with reflection shows that this is what must be happening.
Following sections of the Java language specification are relevant to understanding this behaviour:
Restrictions on the use of fields during initialization. Reflection lets you get to these fields "sooner" than they appear in source code order. If you tried using them directly in a static block that appears before the field declaration you'd get an error regarding an illegal forward reference from the compiler.
Initialization of classes and interfaces.
What constitutes a constant expression.
Final variables. That last paragraph of this section is quite relevant and implies more than its vagueness lets on.
In your class A you have to declare the static fields before the call to your static function.
public static final C field1 = new C("key1", "value1");
public static final C field2 = new C("key2", "value2");
static {
B.load(A.class);
}
The Java tutorial explains it:
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
Related
How can I set or get a field in a class whose name is dynamic and stored in a string variable?
public class Test {
public String a1;
public String a2;
public Test(String key) {
this.key = 'found'; <--- error
}
}
You have to use reflection:
Use Class.getField() to get a Field reference. If it's not public you'll need to call Class.getDeclaredField() instead
Use AccessibleObject.setAccessible to gain access to the field if it's not public
Use Field.set() to set the value, or one of the similarly-named methods if it's a primitive
Here's an example which deals with the simple case of a public field. A nicer alternative would be to use properties, if possible.
import java.lang.reflect.Field;
class DataObject
{
// I don't like public fields; this is *solely*
// to make it easier to demonstrate
public String foo;
}
public class Test
{
public static void main(String[] args)
// Declaring that a method throws Exception is
// likewise usually a bad idea; consider the
// various failure cases carefully
throws Exception
{
Field field = DataObject.class.getField("foo");
DataObject o = new DataObject();
field.set(o, "new value");
System.out.println(o.foo);
}
}
Class<?> actualClass=actual.getClass();
Field f=actualClass.getDeclaredField("name");
The above code would suffice .
object.class.getField("foo");
Unfortunately the above code didn't work for me , since the class had empty field array.
I'm stuck on this problem for almost 3 months now and just can't resolve it myself. I hope it's possible. I'm trying to inject this code with my own custom entity class, which is hard to access, because the class is static and the field is final. Somehow i'm not sure if the generic type is a problem on accessing it.
public class EntityTypes<T extends Entity> {
private final EntityTypes.b<T> aZ;
[some code here]
public interface b<T extends Entity> {
T create(EntityTypes<T> entitytypes, World world);
}
public static class a<T extends Entity> {
private final EntityTypes.b<T> a;
[more code here]
}
}
So far i tried to use Reflections, but i keep getting:
java.lang.IllegalArgumentException: Can not set net.server.EntityTypes$b field net.server.EntityTypes$a.a to net.server.EntityTypes
That is my running code:
// works
ReflectionUtils.setFinal(EntityTypes.class, EntityTypes.VILLAGER, "aZ", (EntityTypes.b<CustomVillager>) CustomVillager::new);
// while this does not work!
ReflectionUtils.setFinal(EntityTypes.a.class, EntityTypes.VILLAGER, "a", (EntityTypes.b<CustomVillager>) CustomVillager::new);
public class ReflectionUtils {
// Does only work on Java 12 and above!!
public static void setFinal(Class cls, Object obj, String fieldName, Object value) {
try {
Field field = cls.getDeclaredField(fieldName);
FieldHelper.makeNonFinal(field);
field.setAccessible(true);
field.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
// For Java 12 final field injection
// https://stackoverflow.com/questions/56039341/get-declared-fields-of-java-lang-reflect-fields-in-jdk12/
public final static class FieldHelper {
private static final VarHandle MODIFIERS;
static {
try {
var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
} catch (IllegalAccessException | NoSuchFieldException ex) {
throw new RuntimeException(ex);
}
}
public static void makeNonFinal(Field field) {
int mods = field.getModifiers();
if (Modifier.isFinal(mods)) {
MODIFIERS.set(field, mods & ~Modifier.FINAL);
}
}
}
}
public class CustomVillager extends EntityVillager {
public CustomVillager(EntityTypes<? extends CustomVillager> entityTypes, World world) {
super(entityTypes, world);
}
}
The exception you are getting means that the Field object represents a field on a class that is different than the class of the the object you are trying to set it on. So in your setFinal() method, you get a Field object representing the field named fieldName on the class cls, and then you try to set that field on the object obj. That means that the object passed in as obj must be an instance of the class cls, or otherwise it won't work.
Looking at the two lines that call setFinal(), the first gets the field aZ in EntityTypes class; this field only exists on an instance of EntityTypes. The second setFinal() call gets the field a in the EntityTypes.a class; this field only exists on an instance of EntityTypes.a. You try to set both of these fields on EntityTypes.VILLAGER. You have not shown the code that declares or initializes EntityTypes.VILLAGER, so we don't know what it is, but these two lines would only work if EntityTypes.VILLAGER were both an instance of EntityTypes and an instance of EntityTypes.a, which is impossible (since they are both classes, neither is a subclass of the other, and Java does not have double inheritance of classes). So one of these two lines must be wrong.
How can I set or get a field in a class whose name is dynamic and stored in a string variable?
public class Test {
public String a1;
public String a2;
public Test(String key) {
this.key = 'found'; <--- error
}
}
You have to use reflection:
Use Class.getField() to get a Field reference. If it's not public you'll need to call Class.getDeclaredField() instead
Use AccessibleObject.setAccessible to gain access to the field if it's not public
Use Field.set() to set the value, or one of the similarly-named methods if it's a primitive
Here's an example which deals with the simple case of a public field. A nicer alternative would be to use properties, if possible.
import java.lang.reflect.Field;
class DataObject
{
// I don't like public fields; this is *solely*
// to make it easier to demonstrate
public String foo;
}
public class Test
{
public static void main(String[] args)
// Declaring that a method throws Exception is
// likewise usually a bad idea; consider the
// various failure cases carefully
throws Exception
{
Field field = DataObject.class.getField("foo");
DataObject o = new DataObject();
field.set(o, "new value");
System.out.println(o.foo);
}
}
Class<?> actualClass=actual.getClass();
Field f=actualClass.getDeclaredField("name");
The above code would suffice .
object.class.getField("foo");
Unfortunately the above code didn't work for me , since the class had empty field array.
Below code is some example analogous to what I am trying to achieve. I have to store the data from internal class but the compiler complains following:
returnedValue=(MyXYZClass)value.toString();
Local variable selectedBusinessArea defined in an enclosing scope must be final or effectively final
private String methodInMainClass(Object someRef){
String returnedValue="";
new SomeInnerClass(Object someRef){
#Override
public String getData(Object value){
if(value instanceof MyXYZClass){
returnedValue=(MyXYZClass)value.toString(); // Not Happening. I cannot assign it to the outer variable.
}
return super.getData(value);
}
}
How can I store the value from the overriden method in internal class?
The local variable in your code sample is returnedValue. It has to be final or effectively final but it's neither declared final nor effectively final since it gets a value assigned.
How to solve this:
All you need is final or effectively final variable which can store the state of returnedValue. There are many ways to do it.
One way would be to define a class like BoxedValue.
public class BoxedValue<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
Using it in the code:
private String methodInMainClass(Object someRef){
BoxedValue<String> returnedValue = new BoxedValue<>("");
new SomeInnerClass(Object someRef){
#Override
public String getData(Object value){
if(value instanceof MyXYZClass){
returnedValue.set((MyXYZClass)value.toString()); // Not Happening. I cannot assign it to the outer variable.
}
return super.getData(value);
}
}
return returnedValue.get();
}
The variable returnedValue is now effectively final.
If you don't want to define an additional class, you can use any other to store the state, i.e. Optional<String> returnedValue = Optional.of("").
You can use an array in order to do the trick
private String methodInMainClass(Object someRef){
String[] returnedValue= {""};
new SomeInnerClass(someRef){
#Override
public String getData(Object value){
if(value instanceof MyXYZClass){
returnedValue[0] = ((MyXYZClass)value).toString(); // Not Happening. I cannot assign it to the outer variable.
}
return super.getData(value);
}
}
// [...]
it is not about inner class this also happened in lambda, the you can not change value of var from out of scope of lambda or inner class, otherwise you may make access issue and for multithread race condition, as workaround you may use one of Atomic family classes for that like AtomicReference<T> or AtomicInteger for ex. :
AtomicInteger count = new AtomicInteger(0);
Runnable r = () -> {
count.getAndIncrement();
};
r.run();
System.out.println(count);
Note here that I used only main thread not created new one to not face race condition.
First of all, sorry for the bad title. I don't know how to describe the problem in a few words (maybe not even in many)...
I am refactoring some settings in our system to be more abstract. The current solution has multiple tables in the DB, one for each settings area. In order to add a new setting, you'll need to extend the schema, the hibernate class, all transfer object classes, getters/setters, etc. I felt that this is violating OCP (open-closed principle), thus the refactoring.
I've spent some time coming up with ideas on how to implement such an abstraction. My favourite idea so far is the following:
1 enum for each settings area
1 enum value for each setting
Each setting is a SettingsDefinition<T> class using a generic type
A SettingsService is using static get/set methods with generic types
So for example, a settings area could be:
public enum SettingsABC{
A(new SettingDefinition<Integer>("A", 123)),
B(new SettingDefinition<String>("B", "Hello")),
C(new SettingDefinition<Boolean>("C", false));
private SettingDefinition settingDefinition;
SettingsABC(SettingDefinition settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition getDefinition() {
return settingDefinition;
}
}
Where the SettingDefinition is the following:
public class SettingDefinition<T> {
private String name;
private T defaultValue;
public SettingDefinition(String name, T defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public T getDefaultValue() {
return defaultValue;
}
}
And the service to get/set the values would be:
public class SettingsService {
public static <T> T getSetting(SettingDefinition setting) {
// hit db to read
// return value
}
public static <T> void setSetting(SettingDefinition setting, T value) {
// hit db to write
}
}
And the consumer would look something like this:
String value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), 123);
My problem is that I cannot enforce a compiler type check between the generic type of the SettingDefinition inside SettingsABC and the generic type of get/set methods of the service. So in essence, I can do this:
Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
Where B's definition is of type String.
Also, I can do this:
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
Where A's definition is an Integer.
Is there any way to use generics to force these two different generic types match?
You can convert the enum to the class:
public final class SettingsABC<T> {
public static final SettingsABC<Integer> A =
new SettingsABC<>(new SettingDefinition<>("A", 123));
public static final SettingsABC<String> B =
new SettingsABC<>(new SettingDefinition<>("B", "Hello"));
public static final SettingsABC<Boolean> C =
new SettingsABC<>(new SettingDefinition<>("C", false));
private final SettingDefinition<T> settingDefinition;
// private constructor, so nobody else would instantiate it
private SettingsABC(SettingDefinition<T> settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition<T> getDefinition() {
return settingDefinition;
}
}
This way individual constants will be typed. Now you can use the type arguments for SettingService as well:
public static <T> T getSetting(SettingDefinition<T> setting) {
...
}
public static <T> void setSetting(SettingDefinition<T> setting, T value) {
...
}
Although it's not an enum anymore, it can be used mostly in the same way. If you need other methods which are usually available in enum, you can mimic them like this:
public String name() {
return settingDefinition.getName();
}
#Override
public String toString() {
return settingDefinition.getName();
}
// and so on