So I've run across something interesting which is incredibly useful. In an enum you can define an abstract method which each of the enum values is forced to provide an implementation for. For example, the following:
public enum Test {
RAWR ("Burninating the country side") {
#Override
public int doStuff() {
return 0;
}
};
private final String enumStuff;
private Test(String enumStuff) {
this.enumStuff = enumStuff;
}
public abstract int doStuff();
}
I added the private variable so you could see how it works in relation to the standard private constructor.
So this makes me wonder: what is RAWR actually, in relation to the Test class? Normally, this kind of syntax would make me think that I'm defining an anonymous inner class, but that doesn't seem intuitive here, since RAWR is anything but anonymous.
The closest thing I can think of is that the values of an enum are in fact extensions of the enum itself, e.g.,
public class RAWR extends Test {
#Override
public int doStuff() {
return 0;
}
}
So, does anyone know what's really going on with this?
From the JLS
An enum declaration specifies a new enum type, a special kind of class type.
[...]
The optional class body of an enum constant implicitly defines an
anonymous class declaration (§15.9.5) that extends the immediately
enclosing enum type.
The JLS also states
For each enum constant c declared in the body of the declaration of E,
E has an implicitly declared public static final field of type E that
has the same name as c. The field has a variable initializer
consisting of c, and is annotated by the same annotations as c.
The enum type you declare is Test. Every enum constant you declare is an instance of a subclass of Test, if it has a body.
Note that enum types are also implicitly final (you wouldn't be able to subclass them). The Java Language only allows this subclassing behavior for enum constants.
This is a very powerful feature of enums, in that not only is each enum a fully fledged class that can have constructors, setters, getters etc but each individual member of the enum can have its own anonymous implementation of the main enum class.
You actually are defining anonymous inner classes. Execute javap -c <classFile> on the class file of your enum to see how the enum looks when compiled.
You will see that an enum is nothing more than a normal class with public static final variables of the same type as the enum. You will also see that for each variable an anonymous inner class is assigned.
Example:
$ javap-c StatusCode.class
public final class de.haufe.StatusCode extends java.lang.Enum<de.haufe.StatusC ode> {
public static final de.haufe.StatusCode CREATED;
public static final de.haufe.StatusCode BAD_REQUEST;
public static final de.haufe.StatusCode UNAUTHORIZED;
public static final de.haufe.StatusCode NOT_FOUND;
public static final de.haufe.StatusCode PRECONDITION_FAILED;
public static final de.haufe.StatusCode UNSUPPORTED_MEDIA_TYPE;
public static final de.haufe.StatusCode UNPROCESSABLE_ENTITY;
public static final de.haufe.StatusCode LOCKED;
public static final de.haufe.StatusCode INTERNAL_SERVER_ERROR;
public static de.haufe.StatusCode[] values();
}
// more stuff
So this is not the best example because none of the enum value implements a method but you may get an idea what an enum actually is.
If you've ever used enums in generics you will have come across E extends Enum<E> which is the right way of defining the type of an enum. It's a little weird but once you get your head around it you can see that it is saying that an enum actually extends an Enum (note the different case) of itself. So essentially yes, all enums in the group seem to extend the base declaring class but the base declaring class is actually an Enum - sort of.
BTW - You can also make enums implement an interface:
interface Something {
int getValue();
}
enum It implements Something {
One,
Two,
Three;
#Override
public int getValue() {
return ordinal();
}
}
Related
I'm studying about java generic classes. Create one generic class with T as type parameter.
public class Genericstring<T> {
String name;
public void set(String name){
this.name = name;
}
public static void main(String[] args){
Genericstring<String> o = new Genericstring<String>();
o.set("Generic");
System.out.println(o.name);
}
}
In above example, the type of T could string, integer or any other type. But is that possible I could create generic class with specific type argument. Like below example, but its showing error "Cannot make a static reference to the non-static type String"
public class Genericstring<String> {
String name;
public static void main(String[] args){
//Here creating object always having string type attributes. No need to specify like did in above example.
}
Can anyone tell me, Is that possible to create generic class with String as parameter Class generictype ? If not, then why ?
Genericstring<String> is declaring a type variable called String.
This makes all other uses of String refer to that type variable, not java.lang.String. Where you've got the argument to main declared as String[], it thinks you mean the type variable. And because this is a static method, you can't refer to that type parameter there, because it belongs to instances of the class.
But is that possible I could create generic class with specific type argument.
What you're describing is a non-generic class. Remove the type parameter.
public class Genericstring {
String name;
// Etc
}
No, you can't.
This code: Genericstring<String> is only naming the Generic Type Variable rather than setting as java.lang.String.
The most you can do is declaring a generic type that extends a specific Class:
public class Genericstring<T extends String>
Example:
abstract class B<T extends String> {
protected T value;
public T getValue() {
return value;
}
public void handleValue() {
System.out.println(this.getValue().substring(0, 5));
}
}
class C extends B<String>{
public C() {
this.value = "Hello World";
}
}
public class A {
public static void main(String[] args) {
C obj = new C();
obj.handleValue(); // prints Hello
}
}
UPDATED: According to the comments, my answer has generated a lot of confusion because the way I've implemented.
#linuxman this is not the only way to accomplish your scenario and your right when you're mentioning Cant we mention like only B or B<T extends String>?:
class B<T extends String> {
protected T value;
public T getValue() {
return value;
}
public void handleValue() {
System.out.println(this.getValue().substring(0, 5));
}
}
public class A {
public static void main(String[] args) {
B obj = new B<String>();
obj.handleValue();
}
}
#Pshemo is right:
In this scenario only type available for is String itself, but if it is only one type then there is no point in having a generic type because it main purse is to allow us to use our class with many types.
Also, about your doubt regarding final classes:
Reference: https://stackoverflow.com/a/5181618/1715121
A final class is simply a class that can't be extended.
(This does not mean that all references to objects of the class would act as if they were declared as final.)
When it's useful to declare a class as final is covered in the answers of this question:
Good reasons to prohibit inheritance in Java?
If Java is object oriented, and you declare a class final, doesn't it stop the idea of class having the characteristics of objects?
In some sense yes.
By marking a class as final you disable a powerful and flexible feature of the language for that part of the code. Some classes however, should not (and in certain cases can not) be designed to take subclassing into account in a good way. In these cases it makes sense to mark the class as final, even though it limits OOP. (Remember however that a final class can still extend another non-final class.)
Related article: Java: When to create a final class
#linuxman What you're trying to accomplish doesn't make sense because the purpose of a Generic Type is to declare contracts that could implement a behavior with different types.
Hope it helps and clears your doubts.
I know that an enum
enum Year
{
First, Second, Third, Fourth;
}
gets converted into
final class Year extends Enum<Year>
{
public static final Year First = new Year();
public static final Year Second = new Year();
public static final Year Third = new Year();
public static final Year Fourth = new Year();
}
When I tried to instantiate enum (not class) I got compile time error as:
error: enum types may not be instantiated
Year y = new Year();
As per my knowledge a private constructor makes a class non instantiable. And I thought that compiler is providing a private constructor. But again I got confused when saw we can define a constructor for enum with default modifier and still cannot create an object of type enum.
enum Year
{
First, Second, Third, Fourth;
Year()
{
}
}
class Example
{
public static void main(String[] args)
{
Year y = new Year();
}
}
My doubt is, if it is not about constructors then what makes enum in Java non instantiable?
It is specified in the Java Language Specification:
8.9. Enum Types
...
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).
Hence the compiler ensures that this requirement is met. Since the compiler "knows" that the type is an enum, it can distinguish between enum Year and final class Year.
Also, no access modifier is allowed for an enum constructor:
8.9.2. Enum Body Declarations
...
It is a compile-time error if a constructor declaration in an enum declaration is public or protected.
...
In an enum declaration, a constructor declaration with no access modifiers is private.
So, in practice, an enum constructor looks like package-scoped (no access modifier), but it really is private.
Finally, the same section also states
In an enum declaration with no constructor declarations, a default constructor is implicitly declared. The default constructor is private, has no formal parameters, and has no throws clause.
This makes the enum non-instantiable even if no constructor is explicitly declared.
An enum in java has a default constructor when it's is not defined and it's private.
Default access modifier has different meanings in different scopes. For example inside a class default access modifier for methods and fields is package private.
Where as in an interface default access modifier means public. In fact there can be no other modifier on an interface field so it's implicitly public.
On a top level class it's package private (where only 2 access modifiers are allowed public and default package private)
So the answer to your question is it is so because compiler decides so. Compiler writer had to uphold the language specification contract.
You're right in thinking that it's a normal class after everything. Every object blueprint type in java is a class which can be represented by java.lang.Class. These restrictions for interfaces, enums, abstract classes, anonymous classes, method local classes are validated by compiler only.
If you can somehow escape the compiler and generate your own byte code for enums or other way around if you can modify the byte code of generated enum class so that it's private constructor becomes public may be you would be able to call it's constructor outside the enum's private scope. You can also try experimenting with reflection to do the same. In fact by generating byte code manually JVM languages like Groovy, Jython, JRuby, Clojure are able to provide functionalities that are not in Java itself. They're bypassing java compiler.
Purpose for having constructor in enums is to be able to set fields of constants in one call. All constants inside an enum are instances of the enum class, so they also consist the fields declared in it.
enum Test
{
T1(1), // equivalent to public static final Test T1 = new Test(1);
T2(2); // equivalent to public static final Test T2 = new Test(2);
int id;
Test(int id)
{
this.id = id;
}
}
And finally bellow is the output of decompiled code for above enum by using java -p Test.class
final class Test extends java.lang.Enum<Test>
{
public static final Test T1;
public static final Test T2;
int id;
private static final Test[] $VALUES;
public static Test[] values();
public static Test valueOf(java.lang.String);
private Test(int);
static {};
}
It should give a better understanding of what happens when the class compiles.
there is a class X;
public final class X {
private X() {}
...
public static enum E {
thingA("1"),
thingB("0")
public boolean isEnabled(){...}
}
...
}
in some another class there a method M
public class AnotherClass{
public void M(){
if (E.thingB.isEnabled()) {
doSomething();
}
}
...
}
i want to test M method, is it possible to use mockito/powermockito to
mock statement within if. to do something like this
when(E.thingB.isEnabled()).thenReturn(true)?
Regardless of whether the enum is nested or not, you can't create or mock a new instance of an enum. Enums are implicitly final, and more importantly, it breaks the assumption that all instances of the enum are declared within the 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. (JLS)
Because all instances of the enum are known at compile time, and all properties of those instances are likewise predictable, usually you can just pass in an instance that matches your needs without mocking anything. If you want to accept an arbitrary instance with those properties, have your enum implement an interface instead.
public interface I {
boolean isEnabled();
}
public enum E implements I { // By the way, all enums are necessarily static.
thingA("1"),
thingB("0");
public boolean isEnabled(){...}
}
I have an abstract class and 2 subclasses. There are 4 constants that relate to all the classes. I was going to place the finals in the abstract class but I understand a final variable is not inherited?
Would I have to define the constant in every class (seems inefficient)? Or just make the constant an instant variable (doesn't sound like a good idea)?
What are ways I can go about this?
The following would be available to all of your sub-classes if defined in the abstract class.
public static final Integer MYCONSTANT = 42;
or
static final Integer MYCONSTANT = 42;
or
protected static final Integer MYCONSTANT = 42;
The second one (package-private) is only available to classes within the same package. The third (protected) would be available to all sub-classes irrespective of their package.
Constants are inherited by childrens. You just have to make sure to have them protected or public so the children can access them.
abstract class A {
protected final static String FOO = "bar";
}
class B extends A {
somemethod() {
System.out.println("foo: " + FOO);
}
}
can be accessed from the class and all its children.
Yes they are. But as they are constant it should be final and static , static modifier make it there will be only one 'copy' and if this will be used only used in subclass only then u can use protected or if from other Classes too the must make it public.
I am new to java and have been scratching my head understanding some its concepts.
I am following the tutorial Java tutorial. However, I cannot find the usefulness of using Static Nested Classes. I mean I think I need some good examples as to why I should want to use it. Can someone provided me some codes as examples so I can understand it better?
thax
The benefit of a static nested class over an "ordinary" class is that you can use it to reflect the relationship between two classes.
For example in the JDK there is java.util.Map and java.util.Map.Entry.
java.util.Map.Entry is declared as a public static interface and doing it this way clearly signposts its relationship to Map. It could have been defined as java.util.MapEntry but doing it as a static nested interface makes it clear that it has a strong relationship to Map.
So you'd probably only use static nested class when the nested class would only ever be used in the context of its parent.
The following example might not be for a Java beginner but one nice example of static nested class is when you want to use the Builder pattern to construct immutable objects of the outer class. The static nested class is allowed to access private members of the outer class thus constructing objects of the outer class although it has a private constructor and initializing private fields of the outer class.
E.g.
public class SomeClass {
private int someField;
private int someOtherField;
private SomeClass()
{}
public static class SomeBuilder {
private int someField;
private int someOtherField;
public SomeBuilder setSomeField(int someField)
{
this.someField = someField;
return this;
}
public SomeBuilder setSomeOtherField(int someOtherField) {
this.someOtherField = someOtherField;
return this;
}
public SomeClass build() throws ValidationException
{
validateFields();
SomeClass someClass = new SomeClass();
someClass.someField = someField;
someClass.someOtherField = someOtherField;
return someClass;
}
private void validateFields() throws ValidationException {
//Validate fields
}
}
public int getSomeField() {
return someField;
}
public int getSomeOtherField() {
return someOtherField;
}
}
Nested or inner class is just an ordinary class defined into other class. The reason to do this is typically to hide inner class from others, i.e. it is yet another level of encapsulation.
Inner class can be private, protected and public that mean exactly the same as for fields and methods.
If inner class is not private you can access it from outside too. Its name is OuterClass.InnnerClass. The nesting depth is not limited by Java specification, so inner class can have its own inner classes etc.
If inner class is not static it has yet another feature: ability to call outer's class methods and fields.
Inner class can be also anonymous. This is very useful for small callbacks, event handlers etc.
Hope this helps. Do not hesitate to ask other more concrete questions.
Another thing I should add is that if an inner class is not static, an instance of it will automatically have a reference to its parent class instance. You can reference it by using: NameOfOuterClass.this.
But if it is static, then it will not.
This, among other things, comes into play during GC (garbage collection).
Because, if an object of the inner class is not being GCed, then the outer class object it references will not be GCed either (in cases where the inner class was not static).