I recently (<- keyword) got into programming Java, and I'm loving it!
But I've ran into a little obstacle while trying to independently program...
My idea was to make a fun little Character Creator - RPG Style, but I don't know how to get the user to select a class without using a bunch of If Statements.
I want to use enum's, even though I'm not really familiar with them.
So far I've got to the point of asking the user what class it wants to play + I've created the enum.
String Name;
System.out.println("Welcome to my Character Creator 2.0!\n");
Thread.sleep(2000);
System.out.print("First off, what do you want your characters name to be?\n\nName : ");
Name = Scan.nextLine();
Thread.sleep(1000);
System.out.print("\nYou are now to be known as "+ Name + "!");
System.out.print("\n\n" + Name + ", what class do you want to be? ");
Thread.sleep(1000);
System.out.print("Classes available : Knight\nMage\nDruid\nNinja\nArcher\nAdventurer");
}
So yeah, I basically want to be able to call out the the classes right from the enum, but I'm unsure how to do it. I tried something stupid like : Class = Scan.nextInt();...
but it obviously didn't work
A simple way you can do this would be to make use of the valueOf method of the Enum class. Something like this:
String name;
...
name = scan.next();
UserClass userClass = UserClass.valueOf(name);
In this case, UserClass is the name of your enum, which might look something like this:
public enum UserClass{
KNIGHT,
MAGE,
DRUID,
NINJA
// other classes as needed
}
Note that the scanner line assumes that the user typed in the name correctly. If they did not, you get an IllegalArgumentException, which you can catch with a try...catch block.
Side note: I'm sure you've seen the messages already, but remember that the java standard is for variable names to begin with a lowercase letter. Otherwise it is hard to determine whether the entity in question is a class (which start with uppercase) or a poorly named variable.
If your enum is called CharacterClass then you have CharacterClass.values() to get a list of the members.
You can then use a for loop to iterate over them printing them out:
for (CharacterClass cc: CharacterClass.values()) {
System.out.println("\t"+cc);
}
In the long run though you will probably find that enums are too limited for your use. You will probably be better off creating a CharacterClass object (potentially subclassing that in different files for each class) and then having a list of available CharacterClasses
Otherwise unless each class is very simple your enum file will end up being massive and very messy/hard to navigate.
What you actually need is a map: string -> class. Using enums makes no sense (though it seems attractive, even to me) since it would introduce the redundancy (the evil), which you try to eliminate in your current approach. You'd better ask for the means to scan the available classes (a packege) and load classes dynamically, by name, instead of asking for enums. The redundancy and enums is something like
// mapping by enumerating the cases
name = Scanner.next()
case name
"knight": load (Druid.class)
"mage": load (Mage.class)
"ninja": load (Ninja.class)
Enjoy the direct approach: load(name). That simple! Just capture exception if no class corresponds to the name.
Related
I know the headline must be not clear enough, I do not know how else to right it in short, so let me explain myself.
I'm doing a java project, where I need to make some form to a class in gui.
Let's say I have the Student class.
Student.java
public class Student {
int studendID;
String studentName;
// and so on...
}
I've heard there is a way to make a gui form of any class i want, so that way the user its self can write the parameters of the class.
In that case it will auto make 2 labels with "studendID" and "studentName" and 2 rooms for text to import the user's choice.
And in case i would like to enter other class, i wouldn't need to build up again all the form to match another class, but it will do it automatic.
I've heard that it is possible, and i have no idea how.
i've tried looking through google, and i found nothing even similiar to it.
You can create a loop in JSP through your fields in the instantiate class,
For example in java :
TestClass test = new TestClass();
Field[] fs = test.getClass().getDeclaredFields();
for (Field field : fs)
{
field.setAccessible(true);
System.out.println( field.getName() + " " + field.get(test) );
}
And create a input Text for each, hope it help
You may use Java Reflection to get fields of a class, and then, make a UI by iterating these fields and let user set the value for each one.
See this other related question: What is reflection and why is it useful?
I can call variables 2 ways.
One is just to do it like this:
MyClass myClass = new MyClass();
myLocalVar = myClass.myVarVal;
And the other way is to use a getter like this:
myLocalVar = myClass.getMyVarVal();
Both ways are working fine, but I was wondering what would be the most efficient/proper way of doing this?
Thanks
Both techniques are terrible, but using the getter is the common (and safer) practice.
In order to access a public data member (a.k.a. public field or public property) of a class, you must know the implementation details of the class (the data member name and the data member type). This is a bad thing; it breaks the OOP concept "information hiding" and increases "coupling".
Using a getter is also bad (as in a bad OOP practice) because objects are not just wrappers around data; objects are supposed to encapsulate functionality and data. "store this here value so I can get it later" is not functionality; it is hoot functionality (as in a monkey in a cage hooting). Getters are; however, an accepted practice in java (and other OOP-lite languages like c++ and c#).
Lest you think I am some ivory tower purest, of course I use getters; I use java, so I use getters.
Getters are fine for getting the work done (no pun), just don't walk around believing that "I R gud OOP Prgmr", because if you use getters you are not a "good oop programmer", you are just a programmer who gets work done.
Edit: Perhaps a better way.
The better way is to not use getters, but to instead design your classes so they expose functionality not data. In practice, there is a point where this breaks down; for example, if you need to display an address on a JSP page, you put a bean in the request (or session or blah) with the address and expose the values using getters. A "more oop pure" way would be to put a bean that exposed "display the address on a jsp" functionality.
Edit2: Perhaps a better example.
Say I work for a phone company, in the USA, and I have an object that represents a customers phone number. This might look like the following:
public class CustomerPhoneNumber
{
private String npa; // numbering plan area (google search nanp for more details)
private String nxx; // exchange.
private String serviceNumber;
public String toString()
{
return "(" + npa + ") " + nxx + "-" + serviceNumber;
}
public boolean equals(Object object)
{
... standard equals implementation (assume this works)
}
}
Now say I get a phone number as an input from a web page in the form String inputPhoneNumber. For the purposes of discussion, the class that receives this input is called "the servlet".
How can I answer this question: "Is the input phone number in my list of CustomerPhoneNumber objects?"
Option 1 is make the npa, nxx, and serviceNumber data members public and access them. This is terrible.
Option 2 is provide getters for npa, nxx, and service number and compare them with the input. Also terrible, too many internal details exposed.
Option 3 is provide a getter that returns the formatted phone number (I called this toString() above). This is smarter but still terrible because the servlet has to know the format that will be used by the getter and ensure that the input is formatted the same way.
Option 4 (I call this "Welcome to OOP") provide a method that takes a String and returns true if that matches the customer service number. This is better and might look like this (the name is long, but sufficient for this example):
public boolean doesPhoneNumberMatchThisInput(final String input)
{
String formattedInput;
String formattedCustomerPhoneNumber = npa + nxx + serviceNumber;
formattedInput = ... strip all non-digits from input.
return StringUtils.equals(formattedCustomerPhoneNumber, formattedInput);
}
This is the winner because no implementation details are exposed. Also the toString can be used to output the phone number on a JSP page.
StringUtils is part of Apache Commons Lang.
For the sake of encapsulation you should always go with the second alternative.
myLocalVar = myClass.getMyVarVal();
Efficiency wise you most likely won't notice a difference.
Do ALWAYS use getter and setter to access your properties!
You should also take a look at this.
myClass.getMyVarVal() is slower since it is a method call and so it creates entrance on the stack for return value, etc. But it is better OOP practice to use getters.
Just create object and object.variablename; or object.methodName(); can be used to make non-static reference...no use of getter is required.
myLocalVar = myClass.getMyVarVal();
it will be good to use it if you are working with OOP concept
Tomcat + Heroku + Maven project:
How to reference Main class static variable:
HEROKU_PRJ_FOLDER\src\main\java\servlet\HelloServlet.java:
import launch.Main;
String my_str = Main.TEST_STRING;
HEROKU_PRJ_FOLDER\src\main\java\launch\Main.java
package launch;
....other imports here....
public class Main {
public static final String
TEST_STRING = "[TEST_STRING]";
public static void main(String[] args){
...somelogic...
};
};
This will probably work for any Tomcat project,
but I did this using Tomcat+Heroku+Maven. Posted answer because
the closest question I could find was this, which I already knew
how to do, just the exact import paths I found a bit confusing for
my particular problem.
For example, say I wanted to "extract" String[] fruits = {"Pear", "Banana", "Apple"}; into three separate variables, eg:
for (int i=0; i != fruits.length; ++i) {
// of course there's no eval in Java
eval("String fruit + i = " + fruits[i] + ";");
}
// ie: code that creates something equivalent to the following declarations:
String fruit0 = "Pear";
String fruit1 = "Banana";
String fruit2 = "Apple";
How could I do that, ignoring the "Why the heck would you want to do that?" question that you might be urged to ask me.
Similar questions have been asked many times before, but the real answer was never given, because what the OP really needed was to use a different approach. That's fine, but is this possible at all?
I have looked at reflection and it doesn't seem like there are any methods that would allow me even to add extra fields to an instance, let alone dynamically create locals.
Is it possible to create variables at runtime in Java?
The simple answer is No.
Java is a static language and does not support the injection of new variable declarations into an existing compiled program. There are alternatives (in order of decreasing usefulness / increasing difficulty):
Represent your "variables" as name / value pairs in a Map. Or come up with some other design that doesn't require real dynamic variables.
Use a scripting language that runs on the JVM and is callable from Java.
Use some kind of templating mechanism to generate new source code containing the declarations, and compile and load it dynamically.
Use a byte code manipulation library (e.g. BCEL) to create class files on the fly and then dynamically load them.
The first approach is the best. Java is a static language, and works best if you don't fight it. If this is a problem for you, maybe you are using the wrong language.
The last two are difficult / complicated and have significant performance costs. They are almost certainly not going to help ...
The question is not why you want to do it but 'what are you going to do with it?'. So suppose at runtime variable with the name fruits2 magically appeared on the stack of your method. Now what? You had to know its name at compile time to take advantage of it. Reflection will not help you access local variables.
Anyway, I would be interested if you described more detailed use case.
The way you phrased your question, people won't understand what you're asking. I believe (if I DO understand) the answer to your question (which should be phrased: "is it possible to dynamically create variables at run time") is "not as you've presented it".
You're right, there's no analog to javascript's (very powerful, but slow and fraught with hazards "eval" function) in Java, and that is precisely what you would need to get this to do what you're hoping to do.
The closest that exists is a hashmap (which is actually pretty close) where you can designate the key at run time, and then set the value. It's fairly versatile as you can have an map that will allow for whatever type you want stored in the field.
You're not going to be able to modify a class that's already been loaded into the JVM. However, you could conceivably use ASM < http://asm.ow2.org/ > or BCEL < http://commons.apache.org/bcel/> to dynamically generate a new class that has the dynamically-defined fields.
Way more trouble than it's worth. Seriously, just use a HashMap!
Would Janino be useful for you?
Here's some code. I think it's close to what you want, but I'm not sure.
package misc;
import java.lang.reflect.InvocationTargetException;
import org.codehaus.janino.CompileException;
import org.codehaus.janino.ScriptEvaluator;
import org.codehaus.janino.Parser.ParseException;
import org.codehaus.janino.Scanner.ScanException;
public class JaninoExample {
public static void main(String[] args) {
String in = " {\"Pear\", \"Banana\", \"Apple\"};";
try {
ScriptEvaluator se = new ScriptEvaluator("return new String[]"+in,String[].class);
try {
String[] fruits = (String[])se.evaluate(new Object[]{});
for(String fruit:fruits){
System.out.println(fruit);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (CompileException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (ScanException e) {
e.printStackTrace();
}
}
}
Yes, for example, see Lombok library and specifically #log4j annotation that injects the log variable to the class
Can you perhaps elaborate, not sure what you're doing different here. Of course you can create three different strings. However i believe the syntax in java is string xx = new string("DDFD");
Edit:
By this i mean, what are you trying to change here. You can allocate memory dynamically therefore you can create "variables" dynamically. HOWEVER you cannot create a "variable" in the primitive fashion such as "int x = 0;" in run time, however you can add nodes to linked lists, resize arrays, etc during run time.
I browsed around for a few answers but had no luck. Actually, it is kinda complicated to explain what I'm trying to do with words, so let's see some snipets:
I have 4 attributes:
private int pageCount; //type 1
private int[] monoColorCount; //type 2
private float cost; //type 3
private int type;
But at any time, an object will have value to only one of these. They are fed by a method that returns a string (parsed from a XML) and depending on the type I will know which one has value. My first attempt was a switch/case, a solution that works but is far from efficient:
switch(type){
case 1: pageCount = Integer.parseInt(QuotasBalance.getUserQuota(user, domain)); break;
case 2: StringTokenizer st = new StringTokenizer(QuotasBalance.getUserQuota(user, domain), "|");
monoColorCount = new int[]{Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())}; break;
case 3: cost = Float.parseFloat(QuotasBalance.getUserQuota(user, domain));
}
Maybe I should've mentioned before: I'm strung to Java 1.4, therefore the StringTokenizer. In this case, I'd have to use a switch/case on type every time I needed this value from an external class:
switch(myQuotaInstance.getType){
case 1: /*Do something with pageCount*/
case 2: /*Do something with monoColorCount*/
case 3: /*Do something with cost*/
}
Needless to say, that's ridiculous. I also tried polymorphism and reflection, but since I fail to grasp completely the concept of reflection yet, that was another dead end. I tried creating a different class to encapsulate only those three attributes which only accounted for delegating the inevitable. Well, I think I made myself clear. Now I'm open to suggestions on how to tackle this problem.
You could grab the strategy pattern. First have an interface.
public interface Strategy {
void execute(QuotaInstance instance);
}
Then have a mapping
private Map strategies = new HashMap();
{
strategies.put(Integer.valueOf(1), new PageCountStrategy());
// ...
}
Then execute it as follows
((Strategy) strategies.get(Integer.valueOf(type))).execute(myQuotaInstance);
Inside the execute() you just access/modify the instance.
#BalusC why Strategy is better here over State? I would suggest state, because it seems natural to me in that type of code, but I remember your "infamous post" about patters, so I guess you are right ;)
Do your Quota objects change their type during their lifetime?
If not, better create three different classes (which can have a common interface or baseclass).
class CostQuota extends Quota {
}
class PageCountQuota extends Quota {
}
class ColorPageCountQuota extends Quota {
}
Each of them can have a string constructor which does the parsing, so you only need a single type switch at creating the object. (But you could also have them be serialized to different XML elements, so no need for the type int at all.)
Well... I studied both Strategy and State patterns and they were totally overkill. Actually, I solved the problem in a very simple (even kinda n00bish) way: I was casting the return value from string to its proper type in my app 3rd layer. When I realised that this value type wouldn't matter until it got to the first layer (UI), I decided to pass it along as a string anyway and in the first layer, I'd switch it (the very way I was doing in the 3rd) and along with the casting, I'm calling a different method to build the UI itself, for it relies on this value type to be built but doesn't rely on the value itself. Yeah, not "elegant" or anything, but in this domain, I think it suits well (overall, the Quota class can be static, actually).
But thanks for the comments, I've gone after both state and strategy patterns and ended up learning (actually, "re-learning") some patterns that will be VERY useful anywhere - such as Method Template and Factory.
Method Template is so obvious, yet so overlooked... ^^
I was thinking about using enum type to manage i18n in a Java game I'm developing but I was curious about performance issues that can occur when working with enums that have lots of elements (thousands I think).
Actually I'm trying something like:
public enum Text {
STRING1,
STRING2,
STRING3;
public String text() {
return text;
}
public String setText() {
this.text = text;
}
}
Then to load them I can just fill the fields:
static
{
Text.STRING1.setText("My localized string1");
Text.STRING2.setText("My localized string2");
Text.STRING3.setText("My localized string3");
}
Of course when I'll have to manage many languages I'll load them from a file.
What I'm asking is
is an obect allocated (in addition to the string) for every element? (I guess yes, since enums are implemented with objects)
how is the right element retrieved from the enum? is it static at compile time? (I mean when somewhere I use Text.STRING1.text()). So it should be constant complexity or maybe they are just replaced during the compiling phase..
in general, is it a good approach or should I look forward something else?
Thanks
Found and adapted a nice mix of enums and ResourceBundle:
public enum Text {
YELL, SWEAR, BEG, GREET /* and more */ ;
/** Resources for the default locale */
private static final ResourceBundle res =
ResourceBundle.getBundle("com.example.Messages");
/** #return the locale-dependent message */
public String toString() {
return res.getString(name() + ".string");
}
}
# File com/example/Messages.properties
# default language (english) resources
YELL.string=HEY!
SWEAR.string=§$%&
BEG.string=Pleeeeeease!
GREET.string=Hello player!
# File com/example/Messages_de.properties
# german language resources
YELL.string=HEY!
SWEAR.string=%&$§
BEG.string=Biiiiiitte!
GREET.string=Hallo Spieler!
You're probably better off using the java.util.ResourceBundle class. It is designed to solve exactly this problem.
To answer your questions:
Yes, there is exactly one instance of each enum value.
Yes, constant complexity for looking up an Enum value.
Not really. Changing the content/behaviour of the enum kinda defeats the purpose of having enums in the first place. They're supposed to represent fixed-range constants with type safety. You can do this kind of thing but that's not what they were designed for.
I hate to hijack to topic, but relying on enums for i18n is going to eventually paint you into a corner. Java has proper i18n support, even going so far as to have a tutorial for it.
although java has i18n support using ResourceBundle I do not think that idea to use enum for this purpose is so bad. I believe that these 2 approaches can be merged. You can create enum Texts that contains all your text identifiers. You can create resource bundles for each supported language and use the same identifiers in this bundle.
Then implement getText() method in the enum as following:
return ResourceBundle.getBundle("texts").getString(name());
So, you do not have to care about the initialization of texts for each language. The standard mechanism cares about this.
Now you use in code the enums and enjoy all features of bundles. You can also create unit test that verifies that all enum members have appropriate lines in bundle and vice versa to avoid garbage in your bundles.
I will probably use this approach in my next project. Thank you for the idea!
Kudos for showing me a compiler error I have never seen before. When compiling the source file generated by:
public static void main(String[] args) throws Exception {
PrintWriter w = new PrintWriter("C:\\test.java");
w.println("enum Test {");
for (int i = 0; i < 3000; i++) {
w.println("c" + i + ",");
}
w.println("}");
w.close();
}
eclipse says
The code for the static initializer is
exceeding the 65535 bytes limit
Same test with a mere 2000 constants compiles flawlessly.
Of course, if you have that many constants, it would be a good idea to organize them into more than one source file.
Yes, one (and only one) object is allocated for every enum constant. With 2000 constants, that's a whopping 16KB memory :-) (on Sun's 32-bit VM, other VMs might differ a little)
Each enum constant is an object, and each of them has a field text. The field is not final, and hence not subject to inlining. Yes, field access is constant-time.
However, in general it's wierd having mutable state in an enum. It's possible, though.
Good approaches include:
Delegate to a ResourceBundle as AlexR shows. Disadvantage: You have to manually manage the resource files. If you do that, I recommend a UnitTest to detect mistyped/missing/superfluous resource keys, or even a command line utility to append the missing keys to the resource file so you don't have to (mis-)type them.
If you only support a few languages, you can alternatively store all languages in the enum:
enum Message {
Hello("Hello", "Hallo", "Salut");
String en;
String de;
String fr;
Message(String en, String de, String fr) {
this.en = en;
this.fr = fr;
this.it = it;
}
Disadvantages: No editing by laymen (needs a compiler), and the source file encoding had better support all special characters in the target language (unicode escapes are awkward ...). Also, the source file gets cluttered if you have more than 3 or 4 languages.
Advantages: Adding/Deleting texts is a snap, and the compiler catches all typos in the name of the text, and the "resource file" is always consistent.
Either way, you should use MessageFormat as the tutorial R.Bemrose links to in his answer explains.
And finally, when working with Enums you might find the values() method handy:
for (Text t : Text.values()) {
}
I agree that an enum is best for the keys of I18n rather than the strings they translate to.
However to your specific problem, you should a constructor rather than a setter. IMHO, In fact you should use a constructor in 90%+ of cases where a value is set on construction and not changed rather than using a setter.
public enum Text {
STRING1("String one"),
STRING2("String two"),
STRING3("String two");
private final String text;
private Text(String text) { this.text = text; }
}
In terms of performance of creating enums, you shouldn't worry about it for a game, clarify and flexibility should be considered first. A 1000 enums might add 1 ms to the startup time of your app. c.f. Loading the text from a file is likely to add 10 ms.