I have an enum which is private, not to be exposed outside of the class. Is there anyway I can do a static import of that type, so that I don't have to type the enum type each time? Or is there a better way to write this? Example:
package kip.test;
import static kip.test.Test.MyEnum.*; //compile error
public class Test
{
private static enum MyEnum { DOG, CAT }
public static void main (String [] args)
{
MyEnum dog = MyEnum.DOG; //this works but I don't want to type "MyEnum"
MyEnum cat = CAT; //compile error, but this is what I want to do
}
}
You can use the no-modifier access level, i.e.
enum MyEnum { DOG, CAT }
MyEnum will not be visible to classes from other packages neither from any subclass. It is the closest form of private, yet letting you avoid explicitly referencing MyEnum.
Considering that you can access the field fully qualified, I would say that it is a bug in the compiler (or language spec) that you cannot statically import it.
I suggest that you make the enumeration package-protected.
It may (or may not) be reasonable to move some of the code into (static) methods of the enum.
If pressed, you could duplicate the static fields in the outer class.
private static final MyEnum CAT = MyEnum.CAT;
private static final MyEnum DOG = MyEnum.DOG;
Icky, but a possibility.
Or is there a better way to write this?
If your main goals are to reference the items without their qualifying enum identifier, and maintain this list privately, you could scrap the enum type altogether and use ordinary private static constants.
You could simply write your code inside the enum itself.
public enum MyEnum {
DOG, CAT;
public static void main(String[] args) {
MyEnum dog = MyEnum.DOG; // this works but I don't want to have to type
// MyEnum
MyEnum cat = CAT; // compile error, but this is what I want to do
}
}
The other place where private enums can be references without their class is in a switch statement:
private static enum MyEnum {
DOG, CAT
}
public static void main(String[] args) {
MyEnum e = null;
switch (e) {
case DOG:
case CAT:
}
}
Nope, that's pretty much what private is all about.
Related
How do I access the property of a child class instead of the abstract class, when handling objects by their parent/abstract class? Like in this example:
public class WordCategories {
public static abstract class Noun {
public static final String TYPE = null;
//... and so on, methods
}
public static class Person extends Noun {
public static final String TYPE = "Person";
// ...
}
}
/* ... then we build a collection with members like: */
nouns.add(new WordCategories.Person("Bill Clinton");
/* now later we need to access a mixed list of nouns: */
for(WordCategories.Noun n: nouns) {
if(n.TYPE.equals("Person") ){ // this is always null
}
Obviously I could just specify (WordCategories.Person) n but that assumes that it is a Person. I need the cast to come from the parent class, and it would be most elegant if it did not involve interpreting the TYPE constant or the use of reflection, for that matter.
You don't have to use reflection at all. If you understand what type it is you like, you can use instanceof to get the specific class instance you care about.
for(WordCategories.Noun n: nouns) {
if(n instanceof WordCategories.Person) {
// cast to WordCategories.Person and perform whatever action you like
WordCategoriesPerson actualPerson = (WordCategories.Person) n;
}
}
This trumps the usage of the field to determine the object type, since the class contains enough metadata for you to want to use in this scenario. While many people would also discourage the use of instanceof due to performance (and frankly, if you wanted a list containing WordCategories.Person, just ask for one), its use in this instance would be cleaner than forcing each child class of WordCategories.Noun to create a method to inform us of what type it is.
static fields are always looked up by static type, so it doesn't matter what you assign to n; n.TYPE will always be WordCategories.Noun.TYPE. Heck, n could even be null:
System.out.println(((WordCategories.Noun) null).TYPE); // Doesn't cause an exception.
There is no way to get n.TYPE to behave the way you want with a static TYPE field. You will need to either make it non-static (and make all your objects bigger in the process), or you will need to change the way you access this data.
Instead of trying to access this through a static field, I recommend using an instance method:
public class WordCategories {
public static abstract class Noun {
public static final String TYPE = null;
public abstract String getType();
//... and so on, methods
}
public static class Person extends Noun {
public static final String TYPE = "Person";
public String getType() {
return TYPE;
}
// ...
}
}
...
for(WordCategories.Noun n: nouns) {
if(n.getType().equals("Person") ){
...
}
}
Try the test case:
public static void main(String[] args) {
Base sub1 = new Sub();
System.out.println(sub1.TYPE); // will print 'BASE'
Sub sub2 = new Sub();
System.out.println(sub2.TYPE); // will print 'SUB'
}
static class Base {
static String TYPE = "BASE";
}
static class Sub extends Base {
static String TYPE = "SUB";
}
If you access static field by the instance, it is decided by instance's declare Class, not the instance's real Class.
In your code for(WordCategories.Noun n: nouns) {, n's declare Class is Noun,so whatever n's real Class is,n.TYPE will only be null.
So, either use directly Class to access static fields, or use non-static field or method. Your usage is not wise, you should just take a different way.
Maybe you just need a non-static method:
public String getType() {
return TYPE;
}
If there is an enum,
public enum Animal {
DOG,
CAT;
}
If I'm understanding enums correctly, we can convert them in equivalent class, something like -
public class Animal {
private static final DOG = 1;
private static final CAT = 2;
}
Is this the correct representation, or I'm missing anything here?
Thanks.
Not exactly. Here is how it will look like:
public class Animal extends Enum<Enum<Animal>> {
public static final DOG = new Animal("DOG", 0);
public static final CAT = new Animal("CAT", 1);
private static final Animal[] values = new Animal[] {DOG, CAT};
private Animal(String name, int ordinal) {super(name, ordinal);}
public static Animal valueOf(String name) {return Enum.valueOf(Animal.class, name)}
public Animal[] values() {return values;}
}
Class java.lang.Enum holds ordinal and name and provides methods that can access them.
No, your code shows how things ware organized before enum was added in Java 1.5.
Your enum values needs to be public not private because you want to make them accessible everywhere.
Also they value is instance of your enum class, not integer (you may want to invoke some methods on these instances like TimeUnit.SECONDS.toMinutes(120); where you invoke toMinutes on instance SECONDS)
So your code looks more like
public class Animal extends Enum<Animal>{
public static final Animal DOG = new Animal();
public static final Animal CAT = new Animal();
//rest of code added by compiler, like
// - making constructor private
// - handling `ordinal()`
// - adding `valueOf(String) ` and `values()` methods
}
I have an enum class which contains an inner class in Java.
For example (In the real code, there are some methods declared on the enum that internally use the inner class):
public enum MyEnum{
VALUE_1,
VALUE_2;
private static class MyInnerClass // is static here needed or can it be removed?
{
}
}
PMD tells me that the 'static' modifier is not needed (Violation of the UnusedModifier rule). Is this correct or would it be a PMD bug?
Note: This question is not a duplicate, it is the inverse of what I ask here.
static keyword is not redundant. You may create a static nested class (with the static keyword) or an inner class (without it). In the first case the class won't be assigned to any particular enum value. In the second case, instances of the inner class need to have an enclosing instance - one of the enum values:
public class Test {
public static void main(String[] args) {
MyEnum.VALUE_1.createInnerObject().showName();
MyEnum.VALUE_2.createInnerObject().showName();
}
public enum MyEnum {
VALUE_1, VALUE_2;
public MyInnerClass createInnerObject() {
return new MyInnerClass();
}
private class MyInnerClass {
public void showName() {
System.out.println("Inner class assigned to " + MyEnum.this + " instance");
}
}
}
}
In the example above you can't create an instance of the MyInnerClass directly from the MyEnum:
new MyEnum.MyInnerClass(); // this will fail
In order to do this, you need to have a static nested class, but then you can't use something like MyEnum.this.
Please forgive the beginner-level question, but I'm confused by the implicit static status of enums.
On one hand, you can't declare them within methods because they are implicitly static, and you can reference them from a static context like any other static class.. but on the other, internally, they refer to themselves as "this" as though they were an instance.
Code sample:
public class EnumTest {
enum Seasons{
SUMMER,
FALL,
WINTER,
SPRING;
public String toString()
{
switch(this)
{
case SUMMER:
return "Hot Summer";
case FALL:
return "Colorful Fall";
case WINTER:
return "Crisp Winter";
case SPRING:
return "Allergy Season";
default
return "wth?";
}
}
}
public static void main(String[] args)
{
System.out.println(EnumTest.Seasons.SUMMER.toString());
}
}
Note how within toString() in the enum definition, there is a switch on "this".
Within the static method main, the Enum is accessed in typical static class manner.
I know that enums are a special type of class, but I'm still trying to understand the reasons for some of their unconventional quirks.
Is there some sort of Factory-pattern type of auto-construction going on when an enum constant is referenced? At exactly what point does it transition from being a static class to an instance?
Thanks!
The constants defined in the enum class are the only things that are implicitly static. It's close to (but not quite equivalent to):
public static final Seasons SUMMER = new Seasons();
public static final Seasons FALL = new Seasons();
public static final Seasons WINTER = new Seasons();
public static final Seasons SPRING = new Seasons();
This allows you to write code such as Seasons.SUMMER.
The rest of the class body is like a normal class body - public String toString() is not implicitly static, therefore it has access to this.
Think of the enum constants as statically declared objects like here:
class A {
public final static A FOO = new A ("FOO");
public final static A BAR = new A ("BAR");
private final String text;
private A(String text) {
this.text = text;
}
public String toString() {
return this.text;
}
}
Although statically declared, the objects for each of the constants can provide non-static methods you can call.
I am attempting to find a way to force Java to load/initialize an enumerated type (which is nested within a class that contains a static Map).
This is important to me because the enumerated type has a constructor that populates said map, and without an explicit way to initialize this enum, the map will remain empty. I have attempted to use Class.forName, but this does not seem to work.
I suppose I could create an instance of the enum (and store it in soem other collection or something), but I would like to know if there is an elegant way to do this.
A class is loaded when you reference a class. This works the same for all classes.
The problem you have is more likely to be that an Enum value is initialised before any static block. i.e. you cannot refer to something initialise in a static block in a constructor. (Generally initialising static content in a constructor is a BAD idea) You need to initialise the Map in the static block, not the constructor.
Try
import java.util.Map;
import java.util.HashMap;
public enum EnumTest {
FOO, BAR, BAZ;
private static final Map<String,EnumTest> map = new LinkedHashMap<String,EnumTest>();
static {
for(EnumTest e : EnumTest.values())
map.put(e.name(), e);
}
public static void main(String... args) {
System.out.println(EnumTest.map);
}
}
Can't you just put initialization of the map in the static initializer of the Enum type?
public enum SomeEnum
{
Member1, Member2, Member3 ...
private static Map<K, SomeEnum> map = ...;
static
{
...populate map...
}
...
EDIT: It appears that the issue was that the Enum member definitions need to come first. I guess I just glossed over this. I fixed the example.
You can just reference something in the enum class. For example:
public class EnumTest {
static final Map<String, MyEnum> map = new HashMap<String, MyEnum>();
enum MyEnum {
FOO, BAR, BAZ;
MyEnum() {
map.put(name(), this);
}
}
static {
// ensure MyEnum is initialized
MyEnum.values();
}
public static void main(String[] argsa) {
System.out.println(map.size());
}
}
Seems like this is exactly why it is often recommended to use accessor methods instead of directly referencing members. Your problem is that the code allows access to the map before it is initialized. Block arbitrary access to the map, and hide it behind an accessor method that makes sure it is initialized.
import java.util.Map;
import java.util.HashMap;
public enum EnumTest {
FOO, BAR, BAZ;
private static Map<String,EnumTest> map = null;
public synchronized static Map getMap() {
if (map == null) {
map = new HashMap<String,EnumTest>();
for ( EnumTest e : EnumTest.values() ) {
map.put( e.name(), e );
}
}
return map;
}
public static void main(String[] args) {
System.out.println( EnumTest.getMap().size() );
}
}