I have an enum class, but I want to display string based on user system language. For example, If the system is English , it should display 1 , 2 ,3
. But if the System is Chinese, the display should totally be different like "一", “二”, “三”. (一 means 1 in Chinese, 二 means 2 in Chinese).
Here is my code
public enum OrderType {
ONE("1"), TWO("2"), THREE("3")
private String name;
private OrderType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static String getEnumByString(String code) {
for (OrderType e : OrderType.values()) {
if (code.equals(e.name)) {
return e.name();
}
}
return null;
}
}
The enum works fine in android, Can I define the String in the value folder,
Like values-iw, values-ru... And how can I use that?
UPDATE:
I also want to use constructor to initialize the enum string. Just like
private OrderType(String name) {
String temp = getResources().getString(R.string.name);
this.name = temp ;
}
But I do not know how to pass parameter of R.string.parameter..
Second, how Can I use getResources() function in enum class
Just provide the String resource ID as a parameter to your Enum:
public enum OrderType {
ONE(R.string.order_type_one),
TWO(R.string.order_type_two)
private final int mTextResourceId;
OrderType(int resourceId) {
mTextResourceId = resourceId;
}
public int getTextResourceId() {
return mTextResourceId;
}
}
Provide these strings in each desired resource folder, e.g.:
res/values/strings.xml
res/values-es/strings.xml
res/values-fr/string.xml
Then, when you want to consume this in a TextView somewhere:
myTextView.setText(myOrderType.getTextResourceId());
No Context passing required, and it is determined at runtime based on the current locale.
You must know that enums are initialized statically. Each of ONE, TWO, THREE is static.
In android to use resources, such as strings, you need a context.
Generally, you can not access Android context in static methods or initializes, therefore you can't use them with enums.
Even if you could use a hack to make android context statically available you would still have issues :
you'd need to ensure none of your OrderType enums accessed before Application#onCreate
strings in your enums won't reflect runtime language changes
Edit
I hope it is clear that you can not reliably initialize your enums with string resources.
You could, however, associate static id of a string (R.string.string_name) with your enum and obtain needed resource string later using a context, as proposed in kcoppock's answer.
You should keep the strings in your string xml resource. That way you can get it from there into your code. For example like this:
String one = getResources().getString(R.string.num_one);
Then you just put a strings.xml file with overloading values in the language folders you want (values-ru, values-sv etc.)
For tasks of that kind use localizations.
"google on i18n java"
and
"android app localization"
public enum OrderType {
One(mActivity.getString(R.string.One)), Two(mActivity.getString(R.string.Two));
private String name;
private OrderType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static String getEnumByString(String code) {
for (OrderType e : OrderType.values()) {
if (code.equals(e.name)) {
return e.name();
}
}
return null;
}
}
also Here is the link, which I think is best way solve the porblem. This developing for API level 11 currently, however this code should run on higher versions. After a quick review in API 16 I did not see an existing core Android solution to this problem, if you know of one please post below and share.
Related
For everyone who is talking about the fact that the object is in an "unitialized state", please refer to the answer to this question which shows that an object reference can be passed around, dereferenced, have methods invoked from it, and have fields accessed before a constructor terminates and all fields have been assigned (including final fields).
So here's the use case:
public class Entity {
private final String name;
public Entity() {
this(toString()); //Nope, Chuck Testa
}
public Entity(String name) {
this.name = name;
}
}
The compiler error is:
Cannot refer to an instance method while explicitly invoking a constructor.
Note that toString() has not been overriden and is the default call from Object.
I'm certainly interested in the philosophical/technical reasons behind this, so if anyone can explain that, that would be an awesome bonus. But I'm looking for a way to call toString() from that default constructor as it refers down to the more specific one with more arguments. The actual use case is a bit more complicated and ends up referring all the way down to a constructor with four arguments, but that shouldn't really matter.
I know I could do something like this...
private static final String TO_STRING_CONSTRUCTOR_ARGUMENT = "aflhsdlkfjlkswf";
public Entity() {
this(TO_STRING_CONSTRUCTOR_ARGUMENT);
}
public Entity(String name) {
this.name = name == TO_STRING_CONSTRUCTOR_ARGUMENT ? toString() : name;
}
... but it seems like a pretty inelegant solution.
So, any way to pull it off? Or any recommended best practices to deal with this situation?
I would prefer not to pass this around until the object is created. Instead I would do this:
public class Entity {
private final String name;
public Entity() {
this(null); // or whatever
}
public Entity(String name) {
this.name = name;
}
public String getName() {
return name != null ? name : Objects.hashCode(this);
}
}
If you can live without the final name, you can use an initializer block:
public class Entity {
private String name;
{name = this.toString();}
public Entity() {
}
public Entity(String name) {
this.name = name;
}
}
this is only available after all calls to this() or super() are done. The initializer runs first after the constructors call to super() and is allowed to access this.
As for the reasons why that is a compiler error, please see section 8.8.7 of the JLS. The reasons why this was made a compiler error are not clear, but consider that the constructor chain has to be the first thing executed when new'ing an Object and look at the order of evaluation here:
public Entity() {
this(toString());
}
toString() is evaluated first before the even the super constructor is invoked. In general this leaves open all kinds of possibilities for uninitialized state.
As a personal preference, I would suggest that everything an object needs to have in order to create valid state should be available within its constructor. If you have no way of providing valid state in a default constructor without invoking other methods defined in the object hierarchy, then get rid of the default constructor and put the onus on the users of your class to supply a valid String to your other constructor.
If you are ultimately just trying invoke the other constructor with the value of toString(), then I would suggest the following instead:
public Entity() {
name = toString();
}
which accomplishes the same goal you set out to achieve and properly initializes name.
As explained in the JLS this is not allowed before the instance is initialized.
However, there are ways to handle your scenario in a consistent manner.
As I see your case, you want to signify either a generated value (toString()) or a user provided value, which can be null.
Given this constraints, using TO_STRING_CONSTRUCTOR_ARGUMENT is failing for at least one specific use case, however obscure it may be.
Essentially you will need to replace the String with an Optional similar to what exists in Google Guava and will be included in Java 8, and seen in many other languages.
Having a StringOptional/StringHolder or whatever you choose, similar to this:
public class StringOptional {
private String value;
private boolean set = false;
public StringOptional() {}
public StringOptional(String value) {
this.value = value;
this.set = true;
}
public boolean isSet() { return set; }
public String getValue() { return value; }
}
Then you can call constructors with the knowledge of the inferred path.
public class Entity {
public Entity() {
this(New StringOptional());
}
public Entity(String s) {
this(new StringOptional(s));
}
private Entity(StringOptional optional) {
super(optional);
}
}
And store this for subsquent need:
if (optional.isSet() ? optional.getValue() : toString();
This is how I usually would handle a maybe-null scenario, hope it augments as an answer.
You cannot 'use' an instance that has not been created yet. By calling a second constructor you are postponing the creation, you cannot use it before the call or in the action of calling.
You can use a static method factory in your class Entity, and put the constructor private:
public class Entity {
private String name;
private Entity() {
}
public Entity(String name) {
this.name = name;
}
public static Entity createEntity() {
Entity result = new Entity();
result.name = result.toString();
return result;
}
}
I know that it isn't possible to extend enum in Java, but I am trying to find an elegant solution for the below
I am trying to model enums (or classes) which will contain http end points of various web services across regions, say I have service A and B, each will have 4 region specific end points in US, EU, JP or CN. (This is basically for some seperate debug code that I am writing, in production the end points will be picked from configuration)
I was hoping to do something like this (not compliant java code).
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum ServiceAEndPoint extends IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
I could do this using interfaces where I have a method for each region, but in my opinion the enum way is more expressive, is there any better way I could model this ? What I am looking for is if there is any better way to model the inheritence relation and also having the expressive power of enumerations.
ServiceAEndPoint.NA_END_POINT
vs
serviceAEndPoint.getNAEndPoint()
I'm assuming that you will also want a ServiceBEndPoint enum (and similar). In which case I don't think your model really makes that much sense.
IEndPoint is really an enumeration of the kind of environments/regions where a service might be running. It is not an enumeration of the services themselves. Each individual service (A, B or whatever) will have different addresses for each of the regions.
Therefore I would stick with just the IEndPoint enum, and then in some service-specific code have a lookup map that will give you the address for a given end-point. Something like this:
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public class ServiceABroker {
private static final Map<IEndPoint, String> addressesByEndPoint;
static {
addressesByEndPoint = new EnumMap<>();
addressesByEndPoint.put(NA_END_POINT, "http://A.com/");
addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/");
addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/");
addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/");
}
public String getAddressForEndPoint(IEndPoint ep) {
return addressesByEndPoint.get(ep);
}
}
If these are static final constants, then just put them in an interface. Name the interface something like IServiceAEndPointKeys, where the keys part is a convention.
Here's where I consider enums to be more appropriate and useful:
Example 1: File type. An enum containing jpg, pdf etc.
Example 2: Column definitions. If I have a table with 3 columns, I would write an enum declaring ID, Name, Description (for example), each one having parameters like column header name, column width and column ID.
Im not sure I understand you question, but you can add methods to an enum for example you could do something like the following:
public enum ServiceAEndPoint{
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
private final String url;
private EndPoint(String url){
this.url=url;
}
public String getURL(){
return url;
}
}
Enums cannot be extended in such a manner, mostly because enums cannot be sub-classed or the constraints they must adhere to will not be possible to impose.
Instead leverage interfaces, like so
public interface IEndPoint;
public enum DefaultEndPoints implements IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum DefaultServiceEndPoints implements IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
public void doSomething(IEndPoint endpoint) {
...
}
The reason why one can't subclass in the manner you wish is related to the contract that enums will be both equal via .equals(object) and via ==. If you could subclass, would this make sense?
if ( (DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) {
}
if you say "yes" then I would expect to be able to do this
DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT;
which would leave a door open for error, as there is no guarantee that a enum entry in one enum declaration is in the other enum declaration.
Could it be different? Perhaps, but it isn't, and changing it would definately introduce a lot of complications that would have to be thoroughly thought out (or it would open avenues to work around Java's strong static-type checking).
You may want to consider something like this:
public abstract class EndpointFactory {
public abstract String getNAEndPoint();
public abstract String getEUEndPoint();
}
public class ServiceAEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://A.com/";
public static final String EU_END_POINT = "http://A-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
public class ServiceBEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://B.com/";
public static final String EU_END_POINT = "http://B-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
Then you can refer to your strings directly like this:
ServiceAEndpointFactory.NA_END_POINT;
Or, you can use the base object if the type of service is not known until execution:
EndpointFactory ef1 = new ServiceAEndpointFactory();
String ep = ef1.getNAEndPoint();
The drawback of this is the redefinition of the get*Endpoint() functions in each sub-class. You could eliminate that by moving the static final variables to be not static in the base class and putting the getter/setter in the base class only one time. However, the drawback of that is you are not able to reference the values without instantiating an object (which essentially emulates what I find valuable with ENUMs).
How does a pattern like this appeal to you? I let the enum implement an interface and implement the interface in a Debug set and a Release set. The release set can then derive the property name from the enum name - which is neat.
public interface HasURL {
public String getURL();
}
public enum DebugEndPoints implements HasURL {
NA,
EU,
JP,
CN;
#Override
public String getURL() {
// Force debug to go to the same one always.
return "http://Debug.com/";
}
}
public enum NormalEndPoints implements HasURL {
NA,
EU,
JP,
CN;
final String url;
NormalEndPoints () {
// Grab the configured property connected to my name.
this.url = getProperty(this.name());
}
#Override
public String getURL() {
return url;
}
}
I use this great Java library for converting a text to speech using Google Translate Unofficial API.
Using this code it is able to "read" the text in English (see Language.ENLGISH):
Audio audio = Audio.getInstance();
InputStream sound = audio.getAudio("I am a bus", Language.ENGLISH);
audio.play(sound);
I have a list (a combobox) with all languages.
How can I convert a string that is "ENGLISH" into the field Language.ENGLISH?
I don't want to use a lot of ifs in the code (if (mySelectedLanguage.equals("ENGLISH") // ...Language.English).
I already tried with:
Language["ENGLISH"] inspired from Javascript, but it doesn't work
Language.class.getField("ENGLISH").toString() (toString because their types are String: public static final String ENGLISH)
Which is the correct way that will really work?
Edit: I already asked here how to get the languages. Maybe it helps us to find the answer.
If you want to get value of public static field
then instead of
Language.class.getField("ENGLISH").toString();
use
(String)Language.class.getField("ENGLISH").get(null);
null indicates that you don't want to get field from some object, but rather from entire class (which in case of static variable is desired behavior)
But if it is possible I would recommend rewriting your Language class to enum and using Language.valueOf("ENGLISH")
Create your own enum to store these values. This is good practice regardless of your particular difficulties - by creating a façade for this third-party class, you de-couple one part of your code.
If you implement toString() as shown below, you can store these enum values directly in your combo box.
public enum Languages {
ENGLISH(Language.ENGLISH, "English"),
// etc..
;
private final String languageName;
private final String displayName;
private Languages(String languageName, String displayName) {
this.languageName = languageName;
this.displayName = displayName;
}
public String getLanguageString() {
return languageName;
}
public String getDisplayString() {
return displayName;
}
public static Languages fromString(String languageString) {
for (Language l : values()) {
if (l.getLanguageString().equals(languageString)) {
return l;
}
}
return null;
}
// optional
#Override
public String toString() {
return displayName;
}
}
Maybe choose a better name than Languages - I'm not feeling very inspired.
Howdy, I am a programmer that has worked almost exclusively with c++/c#/vbs and am just now entering into the world of Android development. I am running into a few issues that I cant seem to find answers for/ dont want to watch lengthy tutorial videos to find out so I figured I would ask here and get a quick answer.
I dont know if this is the best way to do this, so I am open to any suggestions.
I need some custom data containers for my program, lets say I want an 'Achievement' class so I can have an array of them!
now in C# I would do something like
public class Achievment
{
bool locked;
string achName;
string achSubName;
public Achievement(string name, string subname)
{
//ctor code goes here
}
}
Thats not everything I would need but thats the idea of the data layout I would like. However when I try to make a custom class in Eclipse it is all up in my grill about 'Public type achievement must be defined in its own file?' I'm writing this in the application's .java file... Is there somewhere else this should go? I am so confused. Basically java may as well be swahili to me... I like my intuitive c# layouts!
Like essentially I want to store my data separate from my UI, and when I generate an 'Achievement List' it looks at the current user's achievement array and populates from there. Good, bad?
Any answers that are not in the form of a redirect to a tutorial are much appreciated!
You should define the Achievement class in a separate file, called Achievement.java. You also need to change the constructor to have the name name as the class:
...
public Achievement(String name, String subname)
{
//ctor code goes here
}
...
In Java, the type is String, not string.
You either have to remove public modifier from the class (thus its visibility will be default level -- visible only from the package your Application class is placed) OR you need to move your class to Achievment.java file.
In java, public classes are required to be in their own file with the name of the file being the same as the class name (in your example, it must be in Achievment.java).
Create a file called Achievement.java within the source folder in your Eclipse Java project. You would also likely want the class to exist in a package so your assuming your package name was "com.acme", then your Achievement.java file would exist within the following directory structure:
<project-folder>/src/com/acme/Achievement.java
Now, assuming you've done the steps above, you will also need to make the following corrections to the code you posted:
package com.acme // NOTE: This maps to the directory structure
public class Achievement {
private boolean locked;
private String achName;
private String achSubName;
public Achievement(String name, String subname) {
this.achName = name;
this.achSubName = subname;
}
public boolean isLocked() {
return this.locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public String getName() {
return this.achName;
}
public void setName(String name) {
this.achName = name;
}
// etc ...
}
(For those who read my previous question, this is the same teacher and the same project.)
My teacher 'inspected' my code for a web application project and provided some suggestions. One of the suggestions was to use the this keyword even in this situation:
private String getUsername() {
return username;
}
So if I follow his advice, that would become:
private String getUsername() {
return this.username;
}
I asked him why and he told me that there is another usage for the this keyword other than for clearing up ambiguities. A quick googling returned no results for another usage of the this keyword. Even the Java tutorial from Sun mentioned no other usages that would fit in this situation.
this also allows you access to the surrounding class instance and its members from within a nested class, e.g.
public class OuterClass
{
private class InnerClass
{
public OuterClass getOuter()
{
return OuterClass.this;
}
}
}
You use it to chain constructors as well:
public class Foo
{
private final String name;
public Foo()
{
this("Fred");
}
public Foo(string name)
{
this.name = name;
}
}
(For chaining to a superclass constructor, use super(...).)
Additionally, there are some weird times where you can use it from an inner class to specify exactly which member you're after. I don't remember the exact syntax, fortunately - I don't need to use it often.
An very important one that hasn't been mentionned, is the use of this for method chaining used in fluent APIs. In this design pattern, all methods return this, regardless of what they do, allowing you to so stuff like:
dog.setColor("black").setSize("tall").makeDangerous().bark();
using an API constructed, so:
public Dog setColor(String c) {
color=c;
return this;
}
Some people think it is good practice to always use the keyword this for class fields. This can be useful in the following situation:
class MyClass {
private int x = 0;
public void DoSomething(int x) {
int privateFieldValue = this.x; // use field of our class
}
}
Also, you can return this to chain method calls - e.g. in Builder pattern.
class CustomerBuilder
{
private String firstName = "Default";
private String lastName = "Default";
public CustomerBuilder setFirstName(String firstName)
{
this.firstName = firstName;
return this;
}
public CustomerBuilder setLastName(String lastName)
{
this. lastName = lastName;
return this;
}
public Customer build()
{
/* ... do some actions to build a Customer object ... */
}
}
Then, you can use this builder like this:
Customer customer = new CustomerBuilder().setFirstName("John").setLastName("Smith").build();
Always accessing member variables using this. is a coding convention in some places. The idea is probably that it's similar to naming conventions ("All field names must start with an underscore _") but without the ugly name-mangling. (Other places have exactly the opposite convention: avoiding this. unless absolutely necessary).
Personally I don't see any real reason to do it, since all tools you use to access your code should be able to color/style-code each variable/field to make the distinction.
Your grand-dads text-editor is not able to show the difference between accessing a local variable and a field. But that's not a good reason for hard-coding it redundantly in your code.
There is no other usage of the 'this' except for calling another constructor of the same class.
Qualifying access to member variables - even if not needed - is considered best-practice by some developers (I don't). The main point is that it is possible to change the semantics of an assignment without changing that line:
class Foo {
String foo;
void foo() {
// a lot of code
foo = "something"
}
}
May be changed by simply doing the following:
void foo() {
String foo;
// a lot of code
foo = "something"
}
So it's mostly about maintenance and readability - for the price of verbosity.
Using the this keyword will also trigger a warning from the compiler if someone comes along and decides to change the username member to a static variable on you. If you don't use this, the compiler will just play along like everything is cool. And username changing to be static could very well be a bug. So you probably want the warning. And if it isn't a bug, you should change the code that uses username to treat it as if it is static to avoid future bugs / misunderstandings in the code. That way, if someone comes along and changes it back you'll get a new warning.
So, if nothing else, in the context of a getter, it can also trigger compiler warnings when other things change on you. And that is a Good Thing.