Extending enum in Java - java

public enum myEnum {
VAL1(10), VAL2(20), VAL3("hai") {
public Object getValue() {
return this.strVal;
}
public String showMsg() {
return "This is your msg!";
}
};
String strVal;
Integer intVal;
public Object getValue() {
return this.intVal;
}
private myEnum(int i) {
this.intVal = new Integer(i);
}
private myEnum(String str) {
this.strVal = str;
}
}
In the above enum what exactly happens when I add a constant specific class body for VAL3?
The type of VAL3 is definetly a subtype of myEnum as it has overloaded and additional methods. (the class type comes as 'myEnum$1' )
But how can the compiler creates a subtype enum extending myEnum as all the enums are already extending java.lang.enum ?

Your class myEnum inherits from java.lang.Enum. VAL3 is an anonymous inner class that inherits from myEnum called myEnum$1. Think of the enum keyword as syntatic sugar. It sets up classes with normal inheritance trees for you, but will not allow you to extend java.lang.Enum or myEnum directly.

From decompiler
package com.sun.tools.xjc.outline;
public final class Aspect extends Enum
{
public static final Aspect EXPOSED;
public static final Aspect IMPLEMENTATION;
private static final Aspect $VALUES[];
static
{
EXPOSED = new Aspect("EXPOSED", 0);
IMPLEMENTATION = new Aspect("IMPLEMENTATION", 1);
$VALUES = (new Aspect[] {
EXPOSED, IMPLEMENTATION
});
}
public static final Aspect[] values()
{
return (Aspect[])$VALUES.clone();
}
public static Aspect valueOf(String name)
{
Aspect arr$[] = $VALUES;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
Aspect aspect = arr$[i$];
if(aspect.name().equals(name))
return aspect;
}
throw new IllegalArgumentException(name);
}
private Aspect(String s, int i)
{
super(s, i);
}
}

Related

It there better way to cast Int to enum in Java?

I see this question
but I need to define a lot of enum type and do a lot of duplicate work, can every enum extends some thing? like this:
public static enum Type {
;
public final int value;
Type(int v) {
this.value = v;
}
public static Type fromInt(int v) {
for (Type type : values()) {
if (type.value == v) {
return type;
}
}
return null;
}
}
public static enum ENUM1 extends Type{
A(1), B(5), C(10);
}
public static enum ENUM2 extends Type{
D(1), E(20), F(30);
}
As seen in this question, you cannot subclass enums in java. End of story. If you describe in detail what you want to achieve, people might suggest better solution than enums.
About parsing to enum from its' int value, what you have done will work, but it would be better to do something like this:
public enum MyEnum {
A(1),
B(2),
C(3);
private final int value;
MyEnum(int value) {
this.value = value;
}
private static Map<Integer, MyEnum> valueToEnumMap;
public static MyEnum parseFromValue(int value) {
if (valueToEnumMap == null) {
valueToEnumMap = new HashMap<>();
for (MyEnum myEnum : MyEnum.values()) {
valueToEnumMap.put(myEnum.value, myEnum);
}
}
return valueToEnumMap.get(value);
}
}
Initialise a Map with keys the values of the enum, and values the enum itself, and get enums from this map. Depending on your use case, you might want to add check for duplicate keys, currently in case of duplication later pairs will overwrite previous ones.
Alternatively, you could try this.
import java.util.Arrays;
/** Int <-> Enum. */
public class EnumToIntMap
{
/**
*
* Main method.
*
* #param args commandline arguments, should they be needed.
*
*/
public static void main(String[] args)
{
interface Type
{
int value();
static <E extends Enum<E> & Type> E fromValue(Class<E> clazz, final int value)
{
return
Arrays.stream(clazz.getEnumConstants())
.parallel()
.filter(each -> each.value() == value)
.findAny()
.orElseThrow()
;
}
}
enum Enum1 implements Type
{
A(1),
B(5),
C(10),
;
private final int value;
Enum1(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
enum Enum2 implements Type
{
D(1),
E(20),
F(30),
;
private final int value;
Enum2(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
}
}

Enum with generic base class passed as contructor parameter

I'm attempting to create an enum whose constructor accepts an object whose base class is a generic class.
I seem to be unable to fetch the underlying generic type from within the enum however, Object gets returned instead of T.
Is there a way to do this?
abstract public class Field<T> {
abstract public T get();
}
public class IntegerField extends Field<Integer> {
public Integer get() {
return 5;
}
}
public class StringField extends Field<String> {
public String get() {
return "5";
}
}
public enum Fields {
INTEGER (new IntegerField()),
STRING (new StringField());
private final Field<?> field; // <<--- I can't have Field<T>, enum's can't be generic. :(
<T> Fields(Field<T> field) {
this.field = field;
}
public <T> T get() {
return field.get(); // <<--- Returns Object, not T
}
}
The issue is that enums can't be generically typed so even if you cast that get call ((T) field.get()) you won't have type safety because it will agree with any assignment (you could compile this successfully for instance: boolean b = Fields.INTEGER.get()).
Just use constants instead:
public final class Fields {
public static final Field<Integer> INTEGER = new IntegerField();
public static final Field<String> STRING = new StringField();
}
Why do you think an enum is preferable to this?
public final class Fields {
public static final Field<Integer> INTEGER = new IntegerField();
public static final Field<String> STRING = new StringField();
//private ctor
}
or if you prefer
public final class Fields {
public static Field<Integer> integerField() {
return new IntegerField();
}
public static Field<String> stringField() {
return new StringField();
}
//private ctor
}
Why would I want to call Fields.INTEGER.get() when I can just use Fields.INTEGER?

Abstract class constructor param vs. abstract method for final data

What are the pros/cons of using the abstract class constructor vs. an abstract method for passing final data to an abstract class?
Pass via constructor:
public abstract class MyAbstractClass<T> {
private final String type;
private final Function<String, T> factoryFn;
protected MyAbstractClass(String type, Function<String, T> factoryFn) {
this.type = type;
this.factoryFn = factoryFn;
}
public T doSomething(String value) { ... }
}
Pass via abstract method:
public abstract class MyAbstractClass<T> {
abstract String getType();
abstract T getFactoryFn(String value);
public T doSomething(String value) { ... }
}
I'm aware that the abstract methods can potentially be misused, because it doesn't enforce to always return the same value.
But apart from that, is it just a matter of personal preference, or are there any real (dis)advantages for using one over the other?
I hope I am understanding your question correctly..
Usually, when a property of a class is always held in a field, it is more concise to use an abstract constructor. For example, consider the two following scenarios....
// Scenario 1:
abstract class AClass {
final int field;
public AClass(int f) {
field = f;
}
public int getField() {
return field;
}
}
class Class1 extends AClass {
public Class1(int f) {
super(f);
}
// Class Unique Code...
}
class Class2 extends AClass {
public Class2(int f) {
super(f);
}
// Class Unique Code...
}
// Scenario 2:
abstract class AClass {
public abstract int getField();
}
class Class1 extends AClass {
final int field;
public Class1(int f) {
field = f;
}
#Override
public int getField() {
return field;
}
// Class Unique Code...
}
class Class2 extends AClass {
final int field;
public Class2(int f) {
field = f;
}
#Override
public int getField() {
return field;
}
// Class Unique Code...
}
Scenario 1 is shorter since the getter logic for field only needs to be specified once. Whereas in scenario 2, the getter logic must be overridden by both subclasses. I find scenario 2 to be redundant... why write the same code twice when you can use java inheritance to your advantage.
As a final note, I usually don't hold functions in fields unless totally necessary. Whenever you have a function in a field, it's usually a sign that an abstract function can be applied.
Here is your original code with my advice applied...
public abstract class MyAbstractClass<T> {
private final String type;
protected MyAbstractClass(String t) {
type = t;
}
protected abstract T applyFactoryFunction(String value);
public T doSomething(String value) { ... }
}
Hope this helped!

How to create a public static variable that is modifiable only from their class?

I have two classes:
class a {
public static int var;
private int getVar() {
return var; //Yes
}
private void setVar(int var) {
a.var = var; //Yes
}
}
class b {
private int getVar() {
return a.var; //Yes
}
private void setVar(int var) {
a.var = var; //No
}
}
Q: Can i make modifiable member only from his class, for other classes would be constant ?
No, the public access modifier basically allows you to modify the value of the reference from anywhere in your code base.
What you can do is have a private or less-restricted access modifier according to your specific needs, and then implement a getter, but no setter.
In the latter case, remember to add some logic to prevent mutable objects, such as collections, from being mutated.
Example
class Foo {
// primitive, immutable
private int theInt = 42;
public int getTheInt() {
return theInt;
}
// Object, immutable
private String theString = "42";
public String getTheString() {
return theString;
}
// mutable!
private StringBuilder theSB = new StringBuilder("42");
public StringBuilder getTheSB() {
// wrapping around
return new StringBuilder(theSB);
}
// mutable!
// java 7+ diamond syntax here
private Map<String, String> theMap = new HashMap<>();
{
theMap.put("the answer is", "42");
}
public Map<String, String> getTheMap() {
// will throw UnsupportedOperationException if you
// attempt to mutate through the getter
return Collections.unmodifiableMap(theMap);
}
// etc.
}
Just remove setter and make variable private. Then other class only can read the value stetted.
public class a {
private static int var=2;
public static int getVar() {
return var;
}
}
But when you come to Java reflection there is no such protection.
The answer Is NO you can't make a public static variable only modified from its class you can make the variable private and has only public getter or you can add setter private

How to extends Enum in Java?

I have a class from sample project.But when I am using this class it shows some errors.The class is given below.
public class q extends Enum
{
private int i = -1;
private String s = null;
private q(String s, int i)
{
// super(s, i);
this.s = s;
this.i = i;
}
public static q valueOf(String s)
{
return (q)Enum.valueOf(q.class, s);
}
public static q[] values()
{
return (q[])a.clone();
}
public static final q ANDROID_VERSION;
public static final q APP_VERSION_CODE;
public static final q APP_VERSION_NAME;
public static final q AVAILABLE_MEM_SIZE;
private static final q a[];
static
{
APP_VERSION_CODE = new q("APP_VERSION_CODE", 1);
APP_VERSION_NAME = new q("APP_VERSION_NAME", 2);
ANDROID_VERSION = new q("ANDROID_VERSION", 6);
AVAILABLE_MEM_SIZE = new q("AVAILABLE_MEM_SIZE", 11);
q aq[] = new q[34];
aq[0] = APP_VERSION_CODE;
aq[1] = ANDROID_VERSION;
aq[2] = APP_VERSION_NAME;
aq[3] = AVAILABLE_MEM_SIZE;
a = aq;
}
}
When extending Enum it shows "The type q may not subclass Enum explicitly" error.How can i create an enum using these fields?
How can i modify this class to use like enum(ie,I want to use the default enum methods like ordinal(),valueOf(...) etc.. on this.)?
You cannot extend from Enum. You have to declare an Enum class like:
public enum Q {
TYPE1, TYPE2, TYPE3;
}
And you also cannot instantiate an enum class directly. Each type of your enum class is instantiated exactly once by the virtual machine.
public class MyClass {
public enum MyEnum{
TYPE1("Name", 9,1,100000), TYPE2("Name2", 10, 1, 200000);
private final int androidVersion;
private final int appVersionCode;
private final int availableMemSize;
private final String appVersionName;
private MyEnum(String appVersionName, int androidVersion, int appVersionCode, int availableMemSize) {
this.androidVersion = androidVersion;
this.appVersionCode = appVersionCode;
this.availableMemSize = availableMemSize;
this.appVersionName = appVersionName;
}
}
MyEnum mType = MyEnum.TYPE1;
}
Enums basically boil down to something like this:
public Enum Q
{
TYPE1, TYPE2, TYPE3:
}
// is roughy translated to
public final class Q
{
private Q() {}
public static final Q TYPE1 = new Q();
public static final Q TYPE2 = new Q();
public static final Q TYPE3 = new Q();
}
There is more you can do, but this should explain why you can not instantiate Q.
- Think of the enum keyword as syntatic sugar. It sets up classes with normal inheritance trees for you, but will not allow you to extend java.lang.Enum.
Eg:
public enum TEST {
ONE, TWO, THREE;
}

Categories

Resources