Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Right now I'm trying to figure out what exactly is a Enum in java. I know how they work and how/when to use them however I'm a little unclear on what exactly they are. Based on their behavior it seems to me they are nothing more than just a class with a private constructor. However it seems to me that the compiler is doing something special with them as Enums have a special method called values() which doesn't show up in the Enum class on the Oracle doc site.
My question is, what exactly are Enums and how does the compiler interpret them?
An enum is a class that inherits from the Enum class with (a) a private constructor, as you mentioned; and (b) a fixed, ordered list of named, final instances.
Under the covers, when you declare an enum:
public enum Foo {
A(1) {
public void bar() {
System.out.println("A#bar");
}
},
B(2) {
public void bar() {
System.out.println("B#bar");
}
},
C(3) {
public void bar() {
System.out.println("C#bar");
}
};
private Foo(int x) {
// Code goes here...
}
public abstract void bar();
}
...you can imagine the compiler generates something like this:
public class Foo extends Enum<Foo> {
public static final Foo A=new Foo(1) {
public void bar() {
System.out.println("A#bar");
}
};
public static final Foo B=new Foo(2) {
public void bar() {
System.out.println("B#bar");
}
};
public static final Foo C=new Foo(3) {
public void bar() {
System.out.println("C#bar");
}
};
private Foo(int x) {
// Code goes here...
}
}
There are a couple other things that make enums special:
The compiler knows that enums have a fixed list of instances. This allows it to do things like emit warnings if a switch doesn't have a case statement to handle each value.
Each constant has a special, compiler-generated, 0-based, monotonically increasing, dense ordinal() value assigned to it. (In other words, the first has ordinal 0, then second has ordinal 1, and so on.) This allows for extremely efficient array-based data structures like EnumMap to be created.
I'm sure I'm missing a few things, but this is a good place to start.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
my question is more a personnal mind challenge than a production purpose... which means that despite there are obviously better ways to achieve my goal* , I am curious about how - AND IF - I could do it this way.
*I am thus not interested in other ways atm.
I would like to "register" within a list several classes objects (Foo.class, Bar.class, etc.) sharing a common static method inherited from a common parent class.
Then I want to iterate over this list, and invoke that static method.
The following code is wrong indeed, but it may at least show what I am trying to achieve:
======== Classes definition
public class SomeGenericClass {
public abstract static String getType();
}
public class SomeSpecializedClassA extends SomeGenericClass{
public static String getType(){
return "I am of type A";
}
}
public class SomeSpecializedClassB extends SomeGenericClass{
public static String getType(){
return "I am of type B";
}
}
======== Main
class Main{
void main(){
List<Class<SomeGenericClass>> classes = new ArrayList<Class<SomeGenericClass>> ();
classes.add(SomeSpecializedClassA.class);
classes.add(SomeSpecializedClassB.class);
for((SomeGenericClass.class)Class c : classes){
System.out.println(c.getMethod("getType", null).invoke(null, null));
}
}
}
========
Any idea?
sharing a common static method inherited from a common parent class.
This is impossible; static methods do not 'do' inheritance, hence why they are called static methods. There is NO way to specify that a given class adheres to a spec, where 'the spec' involves 'has static method XYZ'.
Why do you think java has the cliché of having 'factories'? A factory is just a container concept where a single instance of a class is the place you ask questions about the concept of another class: A "PersonFactory" is a class for which usually only a single instance exists and it answers questions about persons in general. Most usually the constructor (which doesn't 'do' specs/interfaces either), but anything else goes too.
Then I want to iterate over this list, and invoke that static method.
Reflection can do this. It'd be horrible code style, hard to maintain, and all around entirely the wrong way to go about it. You're asking me: "May I have a gun because there is an annoying mosquito balanced on my left toe", and that's the bazooka. If you want to take it and let er rip, okay. Your funeral.
So what's the better way?
Why is 'static' important here? It's not. Register 'TypeOracle' objects:
public interface CommandHandlerFactory {
String getCommand();
CommandHandler makeHandler();
}
public interface CommandHandler {
void handleCommand(UserInfo sendingUser, String cmdData);
}
public class WelcomeHandler {
#Override
public void handleCommand(UserInfo sendingUser, String cmdData) {
sendMsg("Well hello there, " + sendingUser.getUserName() + "!");
}
}
channelBot.registerHandler(new CommandHandlerFactory() {
#Override
public String getCommand() {
return "/hello";
}
#Override
public CommandHandler makeHandler() {
return new WelcomeHandler();
}
}
That's how you do it in a non-blow-your-feet-right-off fashion.
NB: A comment on your question suggest using asm. This is an utterly nonsensical comment; ASM has nothing to do with this and can't help you. Ignore this comment.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Ok, in this answer here on stack, the poster of the answer shows an example of how you can use abstract methods in an enumeration. I'll repeat that answer here for posterity, albeit slightly-modified to better illustrate the basis of my question.
Consider this enum which uses an abstract method:
public enum Vehicle {
CAR {
public String action() { return "DRIVE!"; }
},
TRUCK {
public String action() { return "DRIVE!"; }
},
BUS {
public String action() { return "DRIVE!"; }
},
TRACTOR {
public String action() { return "DRIVE!"; }
},
MOTORCYCLE {
public String action() { return "RIDE!"; }
},
BOAT {
public String action() { return "SAIL!"; }
},
AIRPLANE {
public String action() { return "PILOT!"; }
};
public abstract String action();
}
As you can see, since 'action' is an abstract function, every single element has to define the override via an anonymous subclass of the enum.
Contrast this with this abstract-free, functionally-equal version which even uses the exact same API:
enum Vehicle {
CAR,
TRUCK,
BUS,
TRACTOR,
MOTORCYCLE,
BOAT,
AIRPLANE;
public String action(){
switch(this)
{
case MOTORCYCLE : return "RIDE!";
case BOAT : return "SAIL!";
case AIRPLANE : return "FLY!";
default : return "DRIVE!";
}
}
}
In this example, you only have to specify the specific cases which differ from a default. Plus, it keeps the values in a nice, clean readable list and reduces a ton of extraneous code as well.
Perhaps I'm missing something, but is there a technical benefit of the abstract method approach? What exactly does it give you that the non-abstract version doesn't? Does it have any extra capabilities?
Note: I suspect the actual answer is because it's not really a function of an enum per se, but rather it's because the enum is compiled to a class and a class supports abstract functions.
However, I'm not exactly sure that's correct either because as others have shown, an enum compiles down to a static final class which means it can't be subclassed. Perhaps the compiler doesn't add the 'final' when using abstract functions. Not sure as I haven't been able to view generated output so I can't say for sure, but that would make sense.
But specifically for this question, is there anything an enum with an abstract function can do that a non-abstract version can't?
The question shouldn't be what one can do over the other because they can both behave in the exactly the same way if programmed correctly.
That is the key part. The version using the switch statement is easy to program incorrectly when adding new items to the enum in the future. Forgetting to specify a case for the new item will cause the default to be used which may not be what you want.
I always use the abstract method version because forgetting to override action() is a compile time error while forgetting to add a new case is a run time error.
The more errors you can catch at compile time, the better.
I'm here mostly to agree with Andreas's answer, but also to add that Java enums let you implement the behavior described in your example in a lot of different ways.
One complaint you had was that since action() was abstract, you had to implement it on every enum constant, and you liked that the switch strategy allowed you to define the default case. Here's another way to do it with a default case:
enum Vehicle {
CAR,
TRUCK,
BUS,
TRACTOR,
MOTORCYCLE {
public String action() { return "RIDE!"; }
},
BOAT {
public String action() { return "SAIL!"; }
},
AIRPLANE {
public String action() { return "PILOT!"; }
};
public String action(){
return "DRIVE!";
}
}
Another complaint you had was that all the boilerplate code made it difficult to scan the enum. If you wanted to reduce boilerplate while still getting compile-time enforcement that each enum constant has its own "action", you could do it this way:
enum Vehicle {
CAR ("DRIVE!"),
TRUCK ("DRIVE!"),
BUS ("DRIVE!"),
TRACTOR ("DRIVE!"),
MOTORCYCLE ("RIDE!"),
BOAT ("SAIL!"),
AIRPLANE ("PILOT!");
private final String action;
Vehicle(String action) {
this.action = action;
}
public String action() {
return action;
}
}
Personally, I love how much Java enums can do, and all the different strategies/techniques they support.
What can a Java enum with abstract functions do that a non-abstracting version without using them can't?
Nothing!
It isn't a question of code ability. It's a question of convenience, code style, and code protection.
You might as well ask: What can an enhanced for-loop do that a regular for-loop can't? Also nothing, but it is a lot more convenient for iterating an Iterable or an array than using the Iterator yourself.
As you showed yourself, you can do the exact same thing using a switch statement, but switch statements are notoriously fragile, i.e. they easily break when changes are made, because it's too easy to forget adding extra case statements when a new value is added.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I got in touch with the functional programming paradigm (haskell, scala) and like the concept. I'm trying to incorporate these functional principles in my every day work.
Here an example
public class Functional
{
private final Object o1;
private final Object o2;
public Functional(Object o1, Object o2)
{
this.o1 = o1;
this.o2 = o2;
}
/*
* method has side effects
*/
private void method()
{
// o1.someChange();
// ...
// o2.someChange();
}
/*
* method has no side effects - it only uses its parameters
*/
private static void method(Object o1, Object o2)
{
// o1.someChange();
// ...
// o2.someChange();
}
public void work()
{
method(o1, o2);
}
public static void main(String[] args)
{
Functional f = new Functional(new Object(), new Object());
f.work();
}
}
I find the static method easier to maintain, also for people who did not write the code, since they just have to look at the method parameters - which can be an advantage in big classes. Another minor advantage is performance, because after compilation static methods get called with invokestatic which is slightly faster.
The public methods are still kept non static, since I don't want to discard OOP/encapsulation. I'm only talking about private static methods.
QUESTION
So what do you think of this apprach? Esp. what are the negativ sides my new habit of making all private methods static - within reason, as long as I don't need more than 3, 4 parameters?
IMHO You should use static methods when
there is no arguments (rare)
there is no way to extend the class of interest e.g. you want to add a method for a String.
you want to add a method to an interface (pre Java 8)
Otherwise a static method is much the same as an instance method where you are taking the first argument implicitly. i.e. you can simply transform one into the other.
Consider these recursive method calls.
class Type {
static ReturnType staticMethod(Type type, Object arg) {
return type.method(arg);
}
ReturnType method(Object arg) {
return staticMethod(this, arg);
}
}
IMHO you should use instance methods for clarity as much as possible, and leave static methods to the rare cases you have no alternative.
Note: you can use functional programming whether you use static method or not. The main principle to remember is a) always return what you create/change as a return value b) don't change any of the arguments, including this for instance methods.
This gives you the flexibility to break this a little to; only change this rather than one of the arguments (and only if you have to)
I have two classes lets say "QuestionOne" and "QuestionsTwo" which are very similar and inherit from a Baseclass "Question". Now I want to write a method which fills a ArrayList with Objects of either class.
public ArrayList<QuestionOne> list = new ArrayList<QuestionOne>();
public void fill(QuestionOne questionOne){
list.add(questionOne);
}
That would be a method to fill QuestionOne objects. But I want the method to be able to fill the list with both type of objects "QuestionOne" and "QuestionTwo".
What I would like to add...I want to use alle methods of "questionOne" and "questionTwo".
How can I achieve this? Do I need an Interface? I don't know...
Make an ArrayList<Question> and fill it up that way. Although you'll only have the interface available, that the Question class exposes.
If you use an abstract class Question, you will be able to use an arraylist of Question to store both subclass objects.
class Question{}
class QuestionOne extends Question{}
class QuestionTwo extends Question{}
ArrayList<Question> list = new ArrayList<Question>();
// This method will take any subclass of Question.
public void fill(Question question){
list.add(question);
}
To backcast, you can use instanceof to compare:
{ //...
for(final Question element:list){
if(element instanceof QuestionOne){
QuestionOne question=(QuestionOne)element;
// Use it here.
}
//...
}
}
public ArrayList<Question> list = new ArrayList<Question>();
Now list.add(x) will work whenever x is a Question or any object of a subclass of Question.
In general, any time you say that a variable or parameter has type C, it can contain a reference to a C or any subclass of C. This applies just as well to the parameter of the ArrayList add routine, which will look like this:
boolean add(Question e)
So you can add anything that is a subclass of Question to your list.
P.S.: Some comments are suggesting changing the parameter of fill also. You can do that, but you don't have to. It depends on your requirements. This will still work:
public void fill(QuestionOne questionOne){
list.add(questionOne);
}
since questionOne is a Question (as well as being a QuestionOne). If you really need to, you could overload fill:
public void fill(QuestionOne questionOne){
System.out.println("I'm adding a Type I question");
list.add(questionOne);
}
public void fill(QuestionTwo questionTwo){
if (questionTwo.isInteresting()) {
// assume isInteresting is a method that is defined only for QuestionTwo
System.out.println("I'm adding a Type II question");
list.add(questionTwo);
}
}
Usually it would be better to do something like this by adding a polymorphic method to Question that is overridden in QuestionOne and QuestionTwo. But this isn't always possible. I'm just bringing this up to point out that the parameter of fill doesn't actually need to change, although you might want to.
As mentioned, you can create an ArrayList of type Question. This means that you will only be able to use methods that are defined in the Question class.
For example
public class Question {
public void askAQuestion(){
System.out.println("Im asking a question");
}
}
_
public class QuestionOne extends Question {
#Override
public void askAQuestion(){
// You can override a method. As long as it has the same name and
// return type, it can have it's own functionality
System.out.println("Im asking question one");
}
public void doSomethingElse(){
// Because this method is not in the Question class, you cannot use
// it in your ArrayList
}
}
_
public class QuestionTwo {
#Override
public void askAQuestion(){
System.out.println("Im asking question two");
}
}
_
public class MainClass {
public static void main (String[] args){
List<Question> questions = new ArrayList<Question>();
questions.add(new QuestionOne());
questions.add(new QuestionTwo());
questions.get(0).askAQuestion(); // Outputs "Im asking question one"
questions.get(1).askAQuestion(); // Outputs "Im asking question two"
}
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Is it good practice in Java for a class's method to redundantly return a modified global field of that class?
Note: I edited the examples below to correct my code.
For example:
public class MyClass {
private String veryImportantString;
public static void main(String [] args) {
MyClass myObject = new MyClass();
myObject.fieldQuestion();
}
public void fieldQuestion() {
veryImportantString = "Hello, StackOverflow";
String newString = addStringToVeryImportantString(" World!");
System.out.println(newString);
}
public String addStringToVeryImportantString(String inputStr) {
this.veryImportantString = veryImportantString + inputStr;
return veryImportantString;
}
}
In the above example, addStringToVeryImportantString is returning veryImportantString, even though as a class field it has been modified and is globally available to the calling method.
In the below example, I do the same thing without returning the field:
public class MyClass {
private String veryImportantString;
public static void main(String [] args) {
MyClass myObject = new MyClass();
myObject.fieldQuestion();
}
public void fieldQuestion() {
veryImportantString = "Hello, StackOverflow";
addStringToVeryImportantString(" World!");
String newString = veryImportantString;
System.out.println(newString);
}
public void addStringToVeryImportantString(String inputStr) {
this.veryImportantString = veryImportantString + inputStr;
}
}
My question is: does it matter? Is there any difference in terms of coding standards, readability, efficiency, etc.? In a way, it makes sense to never return a global class field that a function has modified, because what is the point? The field is available anyway. On the other hand, maybe it makes sense to return the field in order to indicate that the primary purpose of the function is to modify that field and return the value.
Thanks for your input.
It is a usual coding standard for a method to either mutate an object (or variable) or get information about it but never both. Therefore a method that has a return will be assumed at first glance not to have any secondary effects (like changing veryImportantString). This is not a hard and fast rule and there are many reasons to break it but it should never be broken lightly.
Secondly the method signature in the second snippet (with a void return) could only reasonably do one thing; change veryImportantString. But with a return it could do two things; change veryImportantString and return it or return a seperate string based upon veryImportantString. As the void signature is less ambiguous it is preferable (unless theres a specific reason to do otherwise)
For your example, its not particularly important.
In general when you have a private piece of data and a public method. Your only way to get information out to the user of an instance of your class related to the private data is via returning something from a public method. Remember that most Java programs are much more complex and the need to return data related to a private field (java beans for instance) are much more common.