public enum Batman
{
Rat, Cat, Bat;
private boolean isMatch;
// Constructor
Batman()
{
this.isMatch = (this.compareTo(Bat) == 0) ? true : false;
}
public boolean isMatch()
{
return this.isMatch;
}
}
For the constructor line I get the error:
Cannot refer to the static enum field Batman.Bat within an initializer
I am primarily trying to figure out if the specific ENUM can be identified in the constructor.
Also the reason I am thinking of saving the "isMatch" value, is that I don't want to evaluate what it should be every time.
I know form the very beginning, so I just want to save the value, and thus when a call is made it is not an evaluation
but simply passing the value back
I know there are other ways to solve this:
Modify the constructor to accept parameter:
Rat(false), Cat(false), Bat(true);
// Constructor
Batman(boolean isMatch)
{
this.isMatch = isMatch;
}
Change isMatch()
public boolean isMatch()
{
return (this.compareTo(Bat) == 0) ? true : false;
}
Any advice would be great.
Thanks
As others have said, you can not reference a specific Enum value in the constructor. The obvious solution would be to write this:
public enum Batman
{
Rat, Cat, Bat;
public boolean isMatch()
{
return this == Bat;
}
}
(BTW, you don't need equals with Enum)
But if the evaluation this == Bat really bothers you, you can override isMatch for Bat:
public enum Batman
{
Rat, Cat,
Bat {
#Override
public boolean isMatch() {
return true;
}
};
public boolean isMatch()
{
return false;
}
}
This way, you have no comparison, instead you use methods overrided by enum values.
And a variation on this, just for the fun:
public enum Batman
{
Rat, Cat,
Bat {{
this.isMatch = true;
}};
protected boolean isMatch = false;
public boolean isMatch()
{
return isMatch;
}
}
(note the notation{{ }} and the fact that isMatch must be protected instead of private so the Bat instance can access it.)
From Book Effective Java:
Enum constructors aren’t permitted to access the enum’s static fields,
except for compile-time constant fields. This restriction is necessary
because these static fields have not yet been initialized when the
constructors run.
You definitely can't reference any specific ENUM in the constructor, since it needs to be created when you want to refernece it and you are just creating it!
I would go with option 1, as you make the particular knowledge you rely on external to the internal implementation of the enum itself.
Related
I need to achieve this result:
public class question{
public static void main(String[]arg){
A a1=new A();
A a2=new A(2);
assert a2.equals(a1);
}
}
So I have tried:
class A{
A(){
return;
}
A(int x){
return;
}
}
public class d22 {
public static void main(String[]arg){
A a1=new A();
A a2=new A(2);
assert a2.equals(a1);
}
}
But obviously it's not working, is there any way to achieve the code upper? Thx.
There's nothing particularly magical about equals - it's a plain jane method defined in java.lang.Object.
You can override it.
This weird idea would work:
class A {
#Override public boolean equals(Object other) {
return other instanceof A;
}
}
would mean any A is equal to any other.
actually,the java object which is created by the key word new is allocated in the heap.So the result is false if you want compare a1 with a2,because the default equals method is to compare the object memory address.If you want compare two object ,you should rewrite the equals method to achieve your goal.
All classes in Java extends default Object class which contains method's equals() and toString(). Equals() method is used to compare instance of that particular class against another variable. You can override this method to define how equals should behave.
class A {
#Override
public boolean equals(Object other) {
if (!other instance of A) return false; // other is not same type as this class
if (other == this) return true; // both variables point to same object
return true; // you can compare other class attributes here
}
}
By default equals will return true if you are comparing two variables that point to same object. That means in your case that you obtain false when calling equals since your two variables point to different object created by new operator and you have not overriden equals() method to get different behavior than default one.
This question already has answers here:
How to refer to the outer class in another instance of a non-static inner class?
(3 answers)
Closed 8 years ago.
I am currently wondering if there is a good way of implementing an equals method for a non-static inner class in Java. I basically a class Foo with an inner-class Bar like this:
public class Foo {
private final String foo; // constructor omitted
public /* non-static */ class Bar {
private final String bar; // constructor omitted
#Override
public boolean equals(Object other) {
return other != null && other.getClass() == getClass()
&& ((Bar) other).bar.equals(this.bar)
&& Foo.this.equals(Foo.((Bar) other)); // Will, of course, not compile.
}
}
#Override
public boolean equals(Object other) {
return other != null && other.getClass() == getClass()
&& ((Foo) other).foo.equals(foo);
}
}
My classes are a lot more complex in reality and I want to reuse the Foo#equals method from within Bar#equals in order to save me a lot of code. I am now considering to make the "inner-class-relationship" explicit in order to being able to refer to the "outer" class. However, then I have to add accessor methods manually and I want to avoid this. I cannot get rid of the feeling that there should be a Java approach of doing this.
Yes, this is possible. This is often done when you need to pass around "Key" objects that represent a unique identifier for some set of data but do not either have the data or want to transport it.
class SomeData {
private String data;
public static class Key {
private final int firstId;
private final int secondId;
public Key(int firstId, int secondId) {
this.firstId = firstId;
this.secondId = secondId;
}
public boolean equals(Object x) {
if(!(x instanceof Key))
return false;
Key key = ((Key)x);
return this.firstId == key.firstId
&& this.secondId == key.secondId;
}
// implement hashCode as well
}
}
In the example above the inner class is static but that doesn't really matter. The only reason I set it that way is so that exterior classes could construct it. Make sure when you are overriding the .equals that you also get the .hashCode. They should change with each other.
Consider the following enum class
public enum ClassA {
CHECK1("X", 0),
CHECK2("Y", 2),
CHECK3("Z", 1);
private final String id;
private final String cdValue;
private ClsA(String id, String cdValue) {
this.id = id;
this.cdValue = cdValue;
}
private String getId() {
return id;
}
private String getCdValue() {
return cdValue ;
}
private static final List<String> cdValues = new ArrayList<String>();
static {
for (ClassA clsA : ClassA.values()) {
cdValues.add(clsA.getCdValue());
}
}
public boolean isCdValue(String cdValue)
{
if clsValues.contains(cdValue)
return true;
else return false;
}
}
The question that I have is does the method isCdValue has to be static. I have to use this method isCdValue for every input given by the client. Therefore the method parameter cdValue changes for every input.
If it cannot be static then I would like to know how I can access this method. Please note I am primarily interested in learning about static of non-static method call. If it is a non-static call in a enum then how can we call this non static method. I am not trying to resolve the issue of how to get about checking the cdValue exists or not. It is just an example.
does the method isCdValue has to be static.
Yes, the method isCdValue has to be static here.
An enum is a special kind of class. An enum constant defines an instance of the enum type. An enum type has no instances other than those defined by its enum constants. Hence new can not be used to instantiate an enum.
An enum type has no instances other than those defined by its enum
constants. It is a compile-time error to attempt to explicitly
instantiate an enum type (§15.9.1).
Refer this
If you have to put the checking method in the Enum, I think it should be static
you can do this check:
ClassA.isCdValue(para)
Note that, you cannot new an Enum object. So if the method in your Enum, and it is not static, you cannot call it unless you have an Instance. but the goal of your method is checking if the string could be an instance.
another possibility is, use an immutable collection in your Enumm, and make it static and public. Then you could just call ClassA.CD_VALUES.contains(para)
If you want to access it from ClsA, you will have to make it static, if you want to access it from an instance of ClsSa then it doesn't.
A couple of other things: where do you declare clsValues in the first place?
There's no need for the complex if, you may replace this:
public boolean isCdValue(String cdValue)
{
if clsValues.contains(cdValue)
return true;
else return false;
}
with this
public boolean isCdValue(String cdValue){
return clsValues.contains(cdValue)
}
Last little thing, I'd strongly suggest you put curly braces around all your if and else's clauses, I've spent many a debugging hour because someone added a second line under the else, fooled by the indent and thinking it would only execute on the else.
You can use something like this, you do not need static List but the method has to be static as answered by Kent,
public static ClassA getClassAByCDValue(String cdValue)
{
for(ClassA value: ClassA.values())
{
if(value.cdValue.contains(cdValue))
{
return value;
}
}
return null;
}
public static boolean isCDValue(String cdValue)
{
for(ClassA value: ClassA.values())
{
if(value.cdValue.contains(cdValue))
{
return true;
}
}
return false;
}
Using above will be more appropriate as you just have to take care with adding/removing items in enum.
So I have custom class that looks like this:
public class Cell {
protected boolean wasActive;
public Cell() {
this.wasActive = false;
}
public boolean getPreviousActiveState() {
return this.wasActive;
}
public void setPreviousActiveState(boolean previousActiveState) {
this.wasActive = previousActiveState;
}
}
Now I am writing another class here I need to call the above getPreviousActiveState() method:
public class Synapse<Cell> {
private Cell cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
this.cell.getPreviousActiveState; // <= CAN'T BE CALLED. WHY?
}
}
I know the problem has to do with the fact that I declared the class:
public class Synapse<Cell>
but I did this so that only a Synapse can only contain a subclass of Cell. For example I also have implemented a VisionCell, AudioCell, and Neuron class that all extend Cell. Was this use of generics unneccesary? If so, when should I use generics? Thanks!
Defining a type parameter called Cell means is creating some confusion. Let's rename it to T, and also add the pair of missing parenthesis to the this.cell.getPreviousActiveState call:
class Synapse<T> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= CAN'T BE CALLED. WHY?
}
}
The error that you now get is:
The method getPreviousActiveState() is undefined for the type T
Which is the compiler's way of telling you that no where in the code it guaranteed that type parameter T has a getPreviousActiveState() method. Note that Java generic are not like C++ templates: the generic class is compiled once independently of any calling site. In other words: the compiler does not check this class w.r.t to any particular instantiation, but rather it checks that it makes sense on its own.
In order to guarantee that T has a getPreviousActiveState() all you need to do is to specify an upper bound on T that defines this method. We can use Cell itself:
class Synapse<T extends Cell> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= Compiles!
}
}
Of course, you can make the code more versatile by introducing an interface defining the method(s) you're interested in and using this interface as the upper bound. You will also have to make Cell implement this interface:
interface ActiveStateProvider {
public boolean getPreviousActiveState();
}
class Cell implements ActiveStateProvider {
protected boolean wasActive;
public Cell() {
this.wasActive = false;
}
public boolean getPreviousActiveState() {
return this.wasActive;
}
public void setPreviousActiveState(boolean previousActiveState) {
this.wasActive = previousActiveState;
}
}
class Synapse<T extends ActiveStateProvider> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= Compiles!
}
}
I read that from 1.5 we can use enum for singleton
public enum Singleton {
INSTANCE;
//Singleton method
public void someMethod( ) {...}
}
Singleton.INSTANCE.someMethod( );
Does this mean every entry in an enum type is a instance by itself?
If I define a enum type with a class,can I use block synchronization on every entry in teh enum type?
class smokers extends Thread{
public enum restype{
TOBACCO,MATCH,PAPER
}
public void run(){
if(xxxx){
synchronized(restype.PAPER){
....
}
}
else
{
synchronized(restype.MATCH){
....
}
}
}
Is this valid code?
TOBACCO,MATCH,PAPER each is instance of type restype.
You can't modify enum constants, so don't need to synchronize.
If you want to use them as object locks, yes it is valid.
NOTE: Java naming convention suggests that use first letter as Capital letter for class name.
You can read about Enums here.
Since its a constant and has only one instance you don't need synchronization.
But if you are changing values of members using setters then you will need to add synchronization.
public enum Restype {
TOBACCO(1), MATCH(2), PAPER(3);
private int value = 0;//I have purposefully not declare it as final
private Restype(int value) {
this.setValue(value);
}
public void setValue(int value) {// now I can change value in multiple
// threads.
this.value = value;
}
public int getValue() {
return value;
}
}
Now I will have various ways to achieve synchronization for setValue and getValue easiest will be to declare them synchronized.
But clearly above is Misuse of Enums.
In java you can have syncrhonized block on any object so you can have synchronized block on enum instances also.
synchronized (Restype.TOBACCO) {
// Allowed not recommenced
//every class should define its own mutex
}
The code looks valid, but if you need to do that, put the logic in the enum
public enum RestType{
PAPER{
public synchronized void foo(){ return true };
},
MATCH{
public void foo(){ return false };
};
public abstract boolean foo(); //I've never see an abstract method define a
//synchronized method... so I have not
//idea if it's valid
}