Custom Enum in Java - java

I need to implement custom Enum. It should some class which implements Enum methods like valueOf, values and ordinal without directly extending java.lang.Enum. I have been thinking about creating it in such a way where instead of the String should be some generic type T:
public class CustomEnum {
private static int size;
private static final InnerEnum enumValues;
public CustomEnum(){
}
public String valueOf(String innerEnum, String name){
if(name.equals(innerEnum)){
return innerEnum;
}
return null;
}
public InnerEnum values(){
return enumValues;
}
public int ordinal(){}
public static class InnerEnum{
public static String[] data;
public static int number;
}
}
I should be able to give some varying number of parameters (like using varargs) and create constants out of them plus all the enum methods. But I do not really know how to implement all of it. I would be very grateful if someone would help me with that!

Related

Try to understand the usage of functions in a Java enum

Here it's my question, why enums require a static/interface access to methods of a referenced class to work?
Here my code example with an interface, it works I guess because it's an Interface so is not a direct reference to an object implementation:
public interface PredicateBuilder<T extends Comparable> {
Predicate generateGreaterThan(PredicateContent<T> predicateContent);
...
}
Then I can use it in the Enum like this:
public enum Condition {
GREATER_THAN(PredicateBuilder::generateGreaterThan, ">"),
...
public final String operator;
public final BiFunction<PredicateBuilder, PredicateContent<?>, Predicate> predicate;
private Condition(BiFunction<PredicateBuilder, PredicateContent<?>, Predicate> predicate, String operator) {
this.operator = operator;
this.predicate = predicate;
}
}
In that scenario works perfect.
Then I tried the following:
#Component
public class SomeClass {
public String someMethod(String param){
return "Stuff";
}
/* This works
* public static String someMethod(String param){
* return "Stuff";
* }
*/
public void applyStuff(TestEnum enum,String param){
enum.action.apply(param)
}
public enum TestEnum{
OPTION_1(SomeClass::someMethod);
private Function<String,String> action;
private TestEnum(Function<String,String> action){
this.action = action;
}
}
}
At this point the IDE complains because requires an static access to the method, I changed to static methods and it works. So why this limitation? Its because Enums are static so they only can access static/reference methods?
So why this limitation? Its because Enums are static so they only can
access static/reference methods?
No, it is because you are calling a method without instantiating an instance of the Class SomeClass. Which leads to the problem that
Non-static method cannot be referenced from a static context
For instance, the following would work:
public class SomeClass {
public String someMethod(String param){
return "Stuff";
}
}
public enum TestEnum{
OPTION_1(a -> new SomeClass().someMethod("something"));
private Function<String,String> action;
private TestEnum(Function<String,String> action){
this.action = action;
}
}
}
because we initiate an object of the Class SomeClass (i.e., new SomeClass()), and therefore we can use a non-static method.
If you add SomeClass::someMethod you are explicitly telling the compiler that you want the static method named someMethod from the class SomeClass.

Abstract Classes in Java and their object variables

i am wondering what happens with object variables in abstract classes in Java. For example if have this abstract class:
public abstract class BaseClass{
private int[] myNumbers;
public Baseclass(int length){
myNumbers = new int[length];
}
public boolean isOne(int index){
return myNumbers[index] == 1;
}
}
and i have this real class which extends the BaseClass:
public class ArrayClass extends BaseClass{
private int[] myNumbers; //i have to define it again?
public ArrayClass(int length){
super(length); //does this affect my array? I don't think so
}
public void setValue(int index, int value){
if(!isOne(index))
myNumbers[index] = value;
}
}
I want to define basic operations in my BaseClass and do some other stuff in my normal ArrayClass. Because i need an array in my BaseClass i have to define one to work with it in the different methods (obviously).
But in my ArrayClass which extends BaseClass i have to define another array. I am not sure why this is and if it needs to be this way? I hope you understand what i mean. For example i could utilize the BaseClass a second time for this normal class:
public class ArrayClass2 extends BaseClass{
private int[] myNumbers;
public ArrayClass2(int length){
super(length);
}
public int getValue(int index){
if(!isOne(index))
return myNumbers[index];
else
return 1;
}
}
The myNumbers array needs to be protected, not private in order to be accessible from within a sub class.
Read more: https://www.tutorialspoint.com/java/java_access_modifiers.htm
Java has four access types. You can read about them here.
If you want to expose the field in your base class to its children, you can use protected modifier.

Java Utility Singleton With Matching Static Interface

I would like to make a set of utility classes that implement an interface. In order to do this, I will be using the singleton pattern. However, it would also be nice to be able to use those utility classes via static method calls. For example:
public interface IValidator<T> {
boolean isValid(T value);
}
public class StringValidator implements IValidator<String> {
public static final StringValidator instance = new StringValidator();
#Override
public boolean isValid(final String value) {
return true;
}
}
The above provides a singleton which enables me to call the utility methods using an interface, as follows:
// Use case #1
IValidator<String> validator1 = StringValidator.instance;
validator1.isValid("");
// Use case #2
StringValidator.instance.isValid("");
However, I would also like to be able to use StringValidator in the following, more succinct way:
// Use case #3: How can I also allow this syntax?
StringValidator.isValid("");
Is there a way in Java to make all three of the above syntaxes work without renaming the method? The only idea I had was to add a varargs parameter to the static definition, as follows:
public class StringValidator implements IValidator<String> {
public static final StringValidator instance = new StringValidator();
#Override
public boolean isValid(final String value) {
return StringValidator.isValid(value);
}
public static boolean isValid(final String value, final Object... ignored) {
return true;
}
}
However, that fails with the message "Cannot make a static reference to the non-static method isValid(String) from the type StringValidator". Again, is there some way to make the compiler allow all three of my use-case syntaxes? Thanks.
If the interface is a functional interface you could drop the singleton
public class StringValidator {
public static boolean isValid(final String value) {
return ...;
}
}
and whenever you need a instance of Validator<String> use a method handle to the static method:
IValidator<String> validator1 = StringValidator::isValid;
I figured out a way. Change the code to the following:
public interface IValidator<T> {
boolean isValid(T value, Object... ignored);
}
public class StringValidator implements IValidator<String> {
public static final StringValidator instance = new StringValidator();
#Override
public boolean isValid(final String value, final Object... ignored) {
return isValid(value);
}
public static boolean isValid(final String value) {
return true;
}
}
Then all three of the use cases compile. Java will generate a warning for use case #2, but that doesn't bother me as I think the only sane use of the implementing class are cases #1 and #3.

Can i call a static java method when all i have is an object?

I have a class library, that i didn't write, which defines several classes and subclasses, which have static methods. A very much stripped down example:
public class Vehicle {
static String getName() { return "unknown"; }
}
public class Car extends Vehicle {
static String getName() { return "car"; }
}
public class Train extends Vehicle {
static String getName() { return "train"; }
}
Now, i have an object, which is a Vehicle, may be a Car or a Train, and want to call it's getName() function. Again, very much stripped down:
public class SMCTest {
public static void main(String[] args) {
Vehicle vehicle=new Car();
System.out.println(vehicle.getName());
}
}
This prints "unknown", not "car", as the JVM doesn't need, or use, the object to call a static method, it just uses the class.
If that was my code, i'd rewrite vehicle library to use singletons, and non-static methods, but as it isn't my code, i'd rather not touch it.
Is there any way to call the static method of the "real" class of the object, preferable without using reflection? If it helps, i could change the vehicle in the above example to a Class <? extends Vehicle> variable and use that, but i don't see how that helps me to avoid reflection.
preferable without using reflection?
Drop that requirement, and:
vehicle.getClass().getMethod("getName").invoke(null);
would solve the problem as asked.
(However, you should fix the code.)
There is no need for reflection if you know all of the classes involved. With java 8 (create the necessary interface and (anonymous) classes for lower java versions):
public class VehicleUtil {
private static final Map<Class<? extends Vehicle>, Supplier<String>> map = createMap();
private static Map<Class<? extends Vehicle>, Supplier<String>> createMap() {
Map<Class<? extends Vehicle>, Supplier<String>> result = new HashMap<>();
result.put(Vehicle.class, Vehicle::getName);
result.put(Car.class, Car::getName);
result.put(Train.class, Train::getName);
return result;
}
public static String getName(Vehicle vehicle) {
return map.get(vehicle.getClass()).get();
}
public static void main(String[] args) {
System.out.println(VehicleUtil.getName(new Vehicle()));
System.out.println(VehicleUtil.getName(new Car()));
System.out.println(VehicleUtil.getName(new Train()));
}
}
The above is just a more elegant way of doing something like:
public static String getName(Vehicle vehicle) {
return Vehicle.class.equals(vehicle.getClass()) ? Vehicle.getName()
: Car.class.equals(vehicle.getClass()) ? Car.getName()
: Train.class.equals(vehicle.getClass()) ? Train.getName()
: null;
}

Access static method on generic class

I'd like to access a static method on a class, but have that class passed in a generic.
I've done the following:
class Base{
public static String getStaticName(){
return "Base";
}
}
class Child extends Base{
public static String getStaticName(){
return "Child";
}
}
class StaticAccessor{
public static <T extends Base>String getName(Class<T> clazz){
return T.getStaticName();
}
}
StaticAccessor.getName() // --> "Base"
This will return "Base" but what i'd like is "Child" anybody a suggestion without reflections?
You can't do that without reflection, because the type T is erased at runtime (meaning it will be reduced to its lower bound, which is Base).
Since you do have access to a Class<T> you can do it with reflection, however:
return (String) clazz.getMethod("getStaticName").invoke(null);
Note that I'd consider such code to be code smell and that it is pretty fragile. Could you tell us why you need that?
If it is OK for you to pass an object instance rather than Class in your static accessor, then, there is a simple and elegant solution:
public class Test {
static class Base {
public static String getStaticName() { return "Base"; }
public String myOverridable() { return Base.getStaticName(); };
}
static class Child extends Base {
public static String getStaticName() { return "Child"; }
#Override
public String myOverridable() { return Child.getStaticName(); };
}
static class StaticAccessor {
public static <T extends Base>String getName(T instance) {
return instance.myOverridable();
}
}
public static void main(String[] args) {
Base b = new Base();
Child c = new Child();
System.out.println(StaticAccessor.getName(b));
System.out.println(StaticAccessor.getName(c));
}
}
The output is:
Base
Child
I don't believe you can do this without reflection.
It appears you should be doing is not using static methods. You are using inheritance but static methods do not follow inheritance rules.

Categories

Resources