How to dynamically retrieve a constant in java? - java

I have several interfaces all with the same constants - ID and ROOT. I also have a method into which I pass an object that will be an implementation of one of these interfaces.
How can I dynamically retrieve the value of the constant depending on the class passed in - i.e. I want to do something like the following:
public void indexRootNode(Node node, Class rootNodeClass)
{
indexService.index(node, rootNodeClass.getConstant('ID'),
rootNodeClass.getConstant('ROOT'));
}
In PHP this is easy, but is this possible in Java? I've seen this problem solved using accessors on the constant, but I want to retrieve the constant directly. Annotations won't help me here either.
Thanks

This can be achieved using reflection (also see corresponding javadoc).
public void indexRootNode(Node node, Class rootNodeClass)
{
Field idField = rootNodeClass.getField("ID");
Object idValue = idField.get(null);
Field rootField = rootNodeClass.getField("ROOT");
Object rootValue = rootField.get(null);
indexService.index(node, idValue, rootValue);
}
Maybe you may additionaly have to cast the values to the corresponding type.

Please read chapter 19 use interfaces only to define types from Joshua Bloch's Effective Java (in fact, please read the entire book)
Constants do not belong in an interface!!! Constants should be tied to implementing classes, not interfaces.
Either use non-constant methods:
// the implementing classes can define these values
// and internally use constants if they wish to
public interface BaseInterface{
String id(); // or getId()
String root(); // or getRoot()
}
public interface MyInterface1 extends BaseInterface{
void myMethodA();
}
public interface MyInterface2 extends BaseInterface{
void myMethodB();
}
or use an enum to tie things together:
public enum Helper{
ITEM1(MyInterface1.class, "foo", "bar"),
ITEM2(MyInterface2.class, "foo2", "baz"),
;
public static String getId(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getId();
}
public static String getRoot(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getRoot();
}
private static Helper fromInterfaceClass(final Class<? extends BaseInterface> clazz){
Helper result = null;
for(final Helper candidate : values()){
if(candidate.clazz.isAssignableFrom(clazz)){
result = candidate;
}
}
return result;
}
private final Class<? extends BaseInterface> clazz;
private final String root;
private final String id;
private Helper(final Class<? extends BaseInterface> clazz,
final String root,
final String id){
this.clazz = clazz;
this.root = root;
this.id = id;
};
public String getId(){
return this.id;
}
public String getRoot(){
return this.root;
}
}
// use it like this
String root = Helper.fromInterfaceClass(MyInterface1.class).getRoot();

Related

Type-safe way to reuse defensive copy method given immutable class hierarchy

I have a base class and a derived class, both designed to be immutable (ctor and getters omitted):
public class PageQuery<T> {
private final T queryFilter;
private PageCond pageCond; // pagination parameter
// E withPageCond(PageCond newPageCond) {
// return a brand new copy of `this` with `pageCond` replaced with `newPageCond`
// that can be reused across class hierarchy
// }
}
public class PageSortQuery<T> extends PageQuery<T>{
private final SortCond sortCond; // sorting parameter
}
How to add a method that returns defensive copy of this to the base class so that all classes in this hierarchy can benefit from it? Is there a way to accomplish it without clone()?
I don't know if you mean something like this, in this case if you call the withFilter method the origin would not become changed.
#AllArgsConstructor
public class Query <T> {
#Getter
private final String name;
#Getter
private final Predicate<T> filter;
public Query<T> withFilter(Predicate<T> filter){
return new DelegatingQuery<T>(this){
#Override
public Predicate<T> getFilter() {
return Query.this.filter;
}
};
}
static class DelegatingQuery<T> extends Query<T>{
#Delegate
private final Query<T> query;
public DelegatingQuery(Query<T> query) {
super(query.name,query.filter);
this.query = query;
}
}
}

Generic Enum Type for anything extended

I like to make a generic enum that accepts anything.
For this example I use TaskStatus, but in the future, I like to use Generic Enum for example; StudentStatus, this student status can take an id and description itself and it will convert automatically. Moreover, iterate every object and finally automatically return. Is there any chance I can make it?
#Getter
#AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum TaskStatusEnum{
READY(1, "Ready"),
ON_GOING (2,"On going");
private final long id;
private final String description;
public static TaskStatusEnum get (long id)
{
for (TaskStatusEnum status : TaskStatusEnum.values()) {
if (status.id == id) {
return id;
}
}
return null;
}
I'm not sure what exactly you want. You can use interface on enum, then you can use interface as status and dont care what exactly status class is.
public interface Status<E extends Enum<E> & Status<E>> {
public long getId();
public String getDescription();
}
student status:
public enum StudentStatus implements Status<StudentStatus>{
NEW(0, "new");
;
private long id;
private String description;
private StudentStatus(long id, String description) {
this.id=id;
this.description = description;
}
#Override
public long getId() {
return id;
}
#Override
public String getDescription() {
return description;
}
}
task status:
public enum TaskStatus implements Status<TaskStatus>{
OPEN(0, "open");
;
private long id;
private String description;
private TaskStatus(long id, String description) {
this.id=id;
this.description = description;
}
#Override
public long getId() {
return id;
}
#Override
public String getDescription() {
return description;
}
}
generic method to find out status by id
public abstract class StatusUtil {
public static <E extends Enum<E> & Status<E>> E get(Class<E> statusClass, long id) {
return Arrays.asList((E[]) statusClass.getEnumConstants())
.stream()
.filter(item -> item.getId() == id)
.findAny()
.orElse(null);
}
}
example how use:
public class Test {
public static void main(String... args) {
StudentStatus studentStatus = StatusUtil.get(StudentStatus.class, 0);
TaskStatus taskStatus = StatusUtil.get(TaskStatus.class, 0);
List<Status> statusList = Arrays.asList(studentStatus, taskStatus);
statusList.forEach(status -> System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription()));
}
}
if you use JAVA below 8:
public interface Status<E extends Enum<E>> {
public long getId();
public String getDescription();
}
statusUtil:
public abstract class StatusUtil {
public static <E extends Enum<E>> E get(Class<E> statusClass, long id) {
for(E item: (E[]) statusClass.getEnumConstants()) {
if(item.getId() == id) {
return item;
}
}
return null;
}
}
test:
public static void main(String... args) {
StudentStatus studentStatus = StatusUtil.get(StudentStatus.class, 0);
TaskStatus taskStatus = StatusUtil.get(TaskStatus.class, 0);
List<Status> statusList = Arrays.asList(studentStatus, taskStatus);
for(Status status: statusList) {
System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription());
}
}
This you can use in cases, when enums has this same methods and you need common interface
Your enum is effectively final (no subclass allowed)
Apparently you are asking if TaskStatus enum can be subclassed. For example making a StudentStatus that inherits from TaskStatus.
➥ No, enums in Java cannot be subclassed.
Your enum definition actually is a subclass of Enum. That happens in the background, magically handled by the compiler. The inheritance stops there. Your enum definition is effectively final, not allowing further subclasses.
An enum definition can implement an interface. Instances from multiple enum definitions can be treated as all being objects of the same interface. See Answer by Victor1125.
An enum in Java is a convenient way to automatically instantiate one or more name objects, to represent a limited set of values known at compile time. Those instances all pop into existence when their definition class is loaded by the Java classloader. Those objects remain in memory.
You cannot add more instances dynamically at runtime. The entire domain of the enum’s objects is defined at compile time. (Exception: Some crazy twisted reflection/introspection code may be able to create more instances, but I would not go there.)
If you want inheritance, or dynamically created instances, do not use enums. Use regular classes and subclasses, collected into sets or lists. The sets or lists can be marked (< … >) with generics to allow the superclass of their contained elements. For example Set< Animal > can contain objects of the subclasses Dog, Cat, and Bird.
By the way, you can now define an enum in 3 places: its own class, nested within another class, and now in Java 16 (previewed in Java 15), locally inside a method.
Tip: No need to put "Enum" within the name of your enum. Endeavor to invent names for your enum class and enum objects that read naturally. The fact that they happen to be an enum should fade into the background. For example: See Month (Month.JANUARY) and DayOfWeek (DayOfWeek.MONDAY).
How to handle null point on StatusUtil.class
StatusUtil:
public abstract class StatusUtil {
public static <E extends Enum<E>> E get(Class<E> statusClass, long id) {
for(E item: (E[]) statusClass.getEnumConstants()) {
if(item.getId() == id) {
return item;
}
}
return null;
}

Using Non-Static Methods as Enum Properties with Generics

I'll try to keep this short. I'm trying to do something like this:
public enum Fruit {
APPLE("Apple", appleHelper::doAppleThing),
ORANGE("Orange", orangeHelper::doOrangeThing);
private String name;
private Function<String, List<T>> fruitFunction;
Fruit(String name, Function<String, List<T>> fruitFunction) {
this.name = name;
this.fruitFunction = fruitFunction;
}
public String getName() {
return name;
}
public <T> List<T> applyFruitFunction(String someString) {
return fruitFunction.apply(someString);
}
}
Such that later, I can have a method like
private <T> List<T> doFruitThing(String someString, Fruit fruit) {
List<T> transformedFruits = fruit.applyFruitFunction(someString);
if (transformedFruits.isEmpty()) {
throw new FruitException("There was no fruit of type " + fruit.getName());
}
return transformedFruits;
}
There's two problems I'm running into here.
doAppleThing and doOrangeThing are not static methods, and ideally will stay that way, and I can't find any way of creating a local instance of appleHelper and orangeHelper to make the method reference work.
Even if I were to make the methods static, enums can't have Type parameters, so there's no way to have Function<String, List<T>> fruitFunction as a field.
Is there a way this can be done? Or a better approach to this?
Enum values can have their own method implementations. So I would write this as:
public enum Fruit {
APPLE("Apple") {
private final AppleHelper helper = new AppleHelper();
#Override
public <T> List<T> applyFruitFunction(String someString) {
return helper.doAppleThing(someString);
}
},
ORANGE("Orange") {
private final OrangeHelper helper = new OrangeHelper();
#Override
public <T> List<T> applyFruitFunction(String someString) {
return helper.doOrangeThing(someString);
}
};
private String name;
Fruit(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract <T> List<T> applyFruitFunction(String someString);
}
However, if you get to the point of needing per-instance state for enum instances, the thing you have is less and less an enum and more of just an abstract base class. It might be better to look into a more OO approach, using a factory/flywheel pattern for example, rather than being tied to a pure enum for this sort of thing. (It's hard to tell for sure because the code in the question is obviously just a simplified example.)

Overriding Abstract Fields Java

I have an abstract class which has a method used by all classes that extend the class. That method is identical for each class so I don't want to have to write it over and over in those classes. The problem is that the method uses 2 variables that are declared in each class. I can't have the method in the abstract class without having those variables int eh abstract class. But if I do that, they take on the value specified in the abstract class, not the classes that extend it. How can I fix this?
Example code:
public abstract class Example {
public String property1 = ""
public String property2 = ""
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(property1);
propertyList.add(property2);
return property1;
}
}
public class ExampleExtension extends Example {
public String property1 = "this is the property";
public String property2 = "this is the second property";
}
You should limit the scope of the fields to private in the abstract class and declare a constructor for populating the values:
public abstract class Example {
private final String property1;
private final String property2;
protected Example(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}
//...
}
Subclasses would then initialize the field values in their constructors by calling the super constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
super("value1", "value2");
// initialize private fields of ExampleExtension, if any
}
// ...
}
You don't have to override the variables. You can set the initial values of your properties in the constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
property1 = "this is the property";
property2 = "this is the second property";
}
}
A better way is to use a constructor with parameters though, as Mick Mnemonic suggest in the other answer.
IMO Mick's solution is the most pragmatic, although note that you also have the option to make the properties abstract, and then use subclass polymorphicism to require that subclasses override the property implementation:
public abstract class Example {
public abstract String getProperty1();
public abstract String getProperty2();
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return propertyList;
}
}
public class ExampleExtension extends Example {
public String getProperty1() { return "this is the property"};
public String getProperty2() { return "this is the second property"};
}
Make what differs(e.g. property1,property2) abstract method in this case . Search for related reading on template pattern
public abstract class Example {
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return property1;
}
public abstract getProperty1();//overriden by other class that has diff value for property1
public abstract getProperty2();//overriden by other class that has diff value for property2
}

How to best code the following ? Is it doable ? Please see description

As you will see below. I am writing a class named Property that can be bound to any Serializable type as evident from the class description.
Now the value in the property is auto bound to be of type T during compilation.
I want to implement a Class getType() method that should return the Class object of the value at runtime i.e.
Property<String> p = new Property<String>();
Class<String> cl = p.getType();
Here I expect cl to be String.class. Of course one way is:
return value == null ? null : value.getClass();
The issue is it won't reflect in the type returned and returns a raw type of Class object.
Ideally I want it to be of type Class<String>
public class Property<T extends Serializable> implements Serializable {
private T value = null ;
private String name = null ;
private boolean dirty = false ;
private Entity parent = null ;
public Class getType() {
// Here I want to determine the type of T that this object is bound to ?
return class;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
public Entity getParent() {
return parent;
}
public void setParent(Entity parent) {
this.parent = parent;
}
}
In short, you can't, because at runtime the type has been erased.
But, you can do this (abbreviated to just the relevant code):
public class Property<T extends Serializable> implements Serializable {
private T value = null;
private final Class<T> clazz;
// The constructor requires an instance of the Class<T>
public Property(Class<T> clazz) {
this.clazz = clazz;
}
// Return a typed Class object
public Class<T> getType() {
return clazz; // echo back a typed Class object pass to the constructor
}
The Class<T> object passed into the constructor is generally called a "type token".
It is not possible the way you are doing it due to type erasure. One consequence is that this the type that is used to instantiate the type parameter cannot be directly determined at runtime.
Here are a couple of alternatives:
1) Use getClass() to get the type of the value of the Property.
public Class getType() {
return value.getClass();
}
2) Explicitly pass the Class object for the actual type of T as constructor parameter. Note that the generic typing means that you can't accidentally pass the wrong Class object
private T value = null;
private Class<T> type;
public Property(Class<T> type) { this.type = type; }
public Class<T> getType() { this.type; }
There is another approach (which probably won't work here from a design perspective) where you reify the Property classes; e.g.
public class IntegerProperty extends Property<Integer> {
public Class getType() {
returns Integer.class;
}
}
There are clever variations of this where the subclass of the generic class in an anonymous class, and/or you access the type parameter via getClass().getTypeParameters(). But note that the getTypeParameters() approach only works if you've extended a generic class with specific types for the type parameters.
You can write a method
public Class<? extends T> getType() {
return value == null ? null : value.getClass();
}
This will return the runtime type of value, and at compile-time provide as much information about the returned class as possible: it will be T or any subclass of T.
If you want to always return Class<T>, then you have to provide the class as a runtime argument, the way #Bohemian describes it. The type arguments of a generic class aren't available at runtime due to type erasure.

Categories