Enum's toString method and Java good practice - java

I'd like to ask about good coding practice in Java. I want to create a enumeratoin of some properties and override toString() to use it in the following way (JSF 1.2 is used in order to retrieve localized message):
package ua.com.winforce.casino.email.util;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
public enum StatisticItems {
MESSAGES,
VIEWS;
private static String BUNDLE_NAME = "messages";
public String toString(){
switch (this) {
case MESSAGES:
return getLocalizedMsg("messages.title");
case VIEWS:
return getLocalizedMsg("views.title");
default:
return null;
}
}
private static String getLocalizedMsg(String key, Object... arguments) {
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
String resourceString;
try {
ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
resourceString = bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
if (arguments == null) {
return resourceString;
}
MessageFormat format = new MessageFormat(resourceString, locale);
return format.format(arguments);
}
}
My question is about good practice. Is it considered good to put all such methods within a enum definition? If not, I'd like to understand why and of course how to do it better.

There are two points to be made here:
If the default case (returning null in your code) is a runtime error, then using a switch is kind of error prone. There are two better alternatives in my opinion:
Use a field localizationKey, initialized in the constructor of the enum instances, and refer to this key in the toString method
Or, (for more complicated cases) make the toString abstract and force each instance to override with proper implementation. See this question for example.
Many people argue that toString is intended either for really obvious implementations, otherwise only for debugging. (See this question for a good elaboration.) My recommendation: Come up with a more descriptive method name and don't reuse toString just for convenience.
Update: Zooming out from Java semantics a bit: This logic belongs to the view and not the model, as pointed out by BalusC in the comments below.

I would ensure all of that complex logic is done once only at initialise time.
public enum StatisticItems {
MESSAGES("messages"),
VIEWS("views");
final String asString;
StatisticItems(String localised) {
asString = getLocalizedMsg(localised + ".title");
}
#Override
public String toString () {
return asString;
}
private static String BUNDLE_NAME = "messages";
private static final Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
private static String getLocalizedMsg(String key) {
String resourceString;
try {
resourceString = bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
if (arguments == null) {
return resourceString;
}
MessageFormat format = new MessageFormat(resourceString, locale);
return format.format(arguments);
}
}

Related

How to dynamically call static nested classes?

I have the following java code:
...
public final class Constants {
...
public static class Languages {
...
public static class en_US {
public static final String VALIDATION_REGEX = "[a-zA-Z-' ]+";
...
}
public static class en_GB {
public static final String VALIDATION_REGEX = "[a-zA-Z-' ]+";
...
}
}
...
}
My problem is as follows:
I receive a text and a language, and I have to check, whether that text is written only with valid alphabetic characters of that given language.
My code so far is as follows:
...
public boolean isContentValid(String content, String language) {
Boolean isCorrect = false;
switch (language) {
...
case "en_US":
isCorrect = content.matches(Constants.Phrases.en_US.VALIDATION_REGEX);
break;
case "en_GB":
isCorrect = content.matches(Constants.Phrases.en_GB.VALIDATION_REGEX);
break;
...
default:
isCorrect = false;
}
return isCorrect;
}
...
This is fine and works, but as I add languages to my application, I will have to add more and more cases to my switch.
And I was wondering if in Java there is a way to dynamically name a static nested class, something like:
Constants.Phrases[language].VALIDATION_REGEX
So my above code could be something like:
...
public boolean isContentValid(String content, String language) {
return content.matches(Constants.Phrases[language].VALIDATION_REGEX);
}
...
Thank you, and sorry if this is something super easy.
I am a JavaScript developer, and just learning Java.
Looking at you use case maybe this is a better approach:
public enum Language {
en_US("engUS_reg"),
en_GB("engGB_reg");
private final String regex;
Language(String regex) {
this.regex = regex;
}
public String getRegex() {
return regex;
}
}
And using this enum class write your method as follows:
public boolean isContentValid(String content, String language) {
return content.matches(Language.valueOf(language).getRegex());
}
You could use an enum for something like this.
"An enum can, just like a class, have attributes and methods. The only difference is that enum constants are public, static and final (unchangeable - cannot be overridden)." - [w3][1]
public enum Languages {
EN_US {
#Override
public String toString() {
return "[a-zA-Z-' ]+";
}
},
EN_GB {
#Override
public String toString() {
return "[a-zA-Z-' ]+";
}
},
}
And then you can access these values like this
Languages.valueOf("EN_US");
As mentioned by #Pshemo you could avoid a class based approach entirely and use an implementation of Map if you want something a little more lightweight
[1]: https://www.w3schools.com/java/java_enums.asp#:~:text=An%20enum%20can%2C%20just%20like,but%20it%20can%20implement%20interfaces).

Improve design of class hierarchy for a object formatter api

While learning object oriented design I'm judging my own design critically. This framework should be able to print objects in either XML, or JSON, I've stubbed in a basic implementation to avoid getting into details of XML and Json parser apis for now.
So I made the Formatter be the base class. But with my current design, all derivatives of this base class would need to know that they have to call: getFormattedValue() to get output. Also I don't feel comfortable with all of those if else statements in the Formatter constructor. The clients would need to know to pass in either an "xml" or "json" in all derivatives of this class. How can I improve this design to conform to all Object oriented design Principles? Thanks in advance..
public class Formatter {
private String output;
public Formatter(Object object, String formatType){
if(formatType.equals("xml")){
output = getXMLFormat(object);
} else if(formatType.equals("json")) {
output = getJSONFormat(object);
}
}
private String getXMLFormat(Object object){
return "<title>"+object.toString()+"<title>"; // simplified
}
private String getJSONFormat(Object object){
return "{"+object.toString()+"}"; // simplified
}
protected String getFormattedValue(){
return output;
}
}
The derivative class:
public class ItemFormatter extends Formatter {
public ItemFormatter(Employee item, String formatOutput) {
super(item, formatOutput);
}
public void printItem(){
System.out.println(getFormattedValue());
}
}
Split the formatting into multiple classes/interfaces and use a Factory/Factory method in order to get the appropriate formatter. It could look something like this:
public interface Formatter {
String getFormattedValue();
}
and implement a JSonFormatter:
public class JSonFormatter implements Formatter {
String getFormattedValue(Object object) {
return "{"+object.toString()+"}";
}
}
get the correct formatter:
public class FormatterFactory {
public static Formatter getFormatter(String type) { // maybe use enum to decide
if (type.equals("json") {
return new JSonFormatter();
} else if (type.equals("xml")) {
return new XMLFormatter();
}
return new DefaultFormatter(); // returns toString for example
}
}
and finally usage:
String formattedXML = FormatterFactory.getFormatter("xml").getFormattedValue("foobar");
I can't recommend anything for getFormattedValue(), you can probably change the method name to make it more obvious, but that's about it.
With regards to the xml and json, you can probably use Enums.
public Enum EnumFormatType {
FORMAT_XML, FORMAT_JSON;
}
public Formatter(Object object, EnumFormatType formatType) {
if(EnumFormatType.FORMAT_XML.equals(formatType)){
// etc...
}
}
I would start by providing a abstract class to format.
abstract class Formatter {
String format(Object o);
}
Then we specialize two Formatter for XML and JASON
class XMLFormatter extends Formatter {
String format(Object o) {
return "<title>"+o.toString()+"<title>";
}
}
Now you just have to choose which formater you need and just call format on any of them to get the right string.
I think the below code looks more extensible.
public interface IFormatter
{
String GetFormatted(Object object);
}
public class JSonFormatter extends IFormatter
{
public String GetFormatted(Object object)
{
return "{"+object.toString()+"}";
}
}
public class XMLFormatter extends IFormatter
{
public String GetFormatted(Object object)
{
return "<title>"+object.toString()+"<title>";
}
}
public class ItemFormatter
{
public void printItem(Employee item, IFormatter formatter)
{
System.out.println(formatter.GetFormatted(item));
}
}
And it can be called like
itemFormatterInsatnce.printItem(empInstance, formatterInstance);
Also the formatter instance can be resolved using a formatterFactory either through code or configuration.

How to call a method whose name is the value of a string variable in java?

This is the code of the method that I want to simplify. The method name I call of SerializedExpFamMixture class is exactly the value of "model", my question is how to assign the value of "model" directly as the name of the method instead of using "if" to determine which method I should call. Since by using "if", I need to list all the possible values of "model" and judge which method I should use.
Thank you very much for help. I am new to java.
public static SerializedExpFamMixture RateMtxModel(String model)
{
SerializedExpFamMixture result=new SerializedExpFamMixture();
if(model=="kimura1980()")
result=SerializedExpFamMixture.kimura1980();
if(model=="accordance()")
result=SerializedExpFamMixture.accordance();
if(model=="pair()")
result=SerializedExpFamMixture.pair();
return result;
}
One way you can approach this is to use Reflection:
Method method = myClass.getClass().getMethod("doSomething", null);
method.invoke(myClass, null);
Since you are new to Java, it's time for some general pointers:
In Java, we usually name our methods with camelCase, so the first letter is lower case.
Also, in Java we usually leave the opening curly-bracket on the same line as the code (no newline).
Always use final on your variables. At least your parameters. That way you won't overwrite it, and thus won't have to try to figure out which value it actually has at runtime.
Use curly-brackets! Please!
The result variable is not actually needed.
Use the equals-method to compare Strings.
If you only want one result, use else-if
Fixing these things, your method looks like this:
public static SerializedExpFamMixture rateMtxModel(String model) {
if (model.equals("kimura1980()")) {
return SerializedExpFamMixture.kimura1980();
} else if (model.equals("accordance()")) {
return SerializedExpFamMixture.accordance();
} else if(model.equals("pair()")) {
return SerializedExpFamMixture.pair();
}
return new SerializedExpFamMixture();
}
Next, let's look at what you are actually trying to do here. You want to pass some Strings around, and use them as a basis for creating objects. And now, with the advice given here, you will do this using reflection. This does not sound like a very good idea to me. Say you were to go through with this, and this happened:
rateMtxModel("kinura1980");
Small typo, hard to spot, will give unexpected results. If you were actually calling a method the compiler would let you know that you messed up, now you will get no warning (btw did you see both errors in that method call?). The same if someone were to delete the accordance()-method, the compiler would not alert them that this will break the program.
If it was up to be I would just use the static factory-methods in SerializedExpFamMixture directly, but if you have to do it like this (if the task at hand is using a String input to create an object) I would do something like this:
public enum Something {
KIMURA1980("kimura1980()"),
ACCORDANCE("accordance()"),
PAIR("pair()");
private final String stringValue;
private Something(final String stringValue) {
this.stringValue = stringValue;
}
public static Something fromString(final String string) {
for (final Something something : values()) {
if (something.stringValue.equals(string)) {
return something;
}
}
return null;
}
}
public static SerializedExpFamMixture rateMtxModel(final String model) {
if (model == null) {
throw new IllegalArgumentException("model is null!");
}
final Something something = Something.fromString(model);
if (something == null) {
return new SerializedExpFamMixture();
}
switch(something) {
case KIMURA1980:
return SerializedExpFamMixture.kimura1980();
case ACCORDANCE:
return SerializedExpFamMixture.accordance();
case PAIR:
return SerializedExpFamMixture.pair();
default:
return new SerializedExpFamMixture();
}
}
This way, the one place where you will use the Strings is in the enum, the rest of the code will use the enum constants and thus have the safety of the compiler to rely on.
One could also leave the linking between operation and String to the enum, like this:
interface Operation<T> {
public T run();
}
public enum Something {
KIMURA1980("kimura1980()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.kimura1980();
}
}) ,
ACCORDANCE("accordance()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.accordance();
}
}),
PAIR("pair()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.pair();
}
}),
DEFAULT(null, new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return new SerializedExpFamMixture();
}
});
private final String stringValue;
private final Operation<SerializedExpFamMixture> operation;
private Something(final String stringValue, final Operation<SerializedExpFamMixture> operation) {
this.stringValue = stringValue;
this.operation = operation;
}
public static Something fromString(final String string) {
if (string != null) {
for (final Something something : values()) {
if (string.equals(something.stringValue)) {
return something;
}
}
}
return DEFAULT;
}
public SerializedExpFamMixture getCorrespondingSerializedExpFamMixture() {
return operation.run();
}
}
With this setup in the enum (I think the Operation-part can be trimmed out with Java8), the method will be as simple as:
public static SerializedExpFamMixture rateMtxModel(String model) {
return Something.fromString(model).getCorrespondingSerializedExpFamMixture();
}
Use reflection, but you need to consider a few things:
Bug alert! Comparing Strings using == doesn't work as expected in java - use .equals() instead. However, the solution below bypasses that problem
For the general case, which includes methods not visible to the invoker, you need to consider accessibility, both in finding the method and invoking it
You don't need the result variable, and even if using your code, don't need to initialize it
Try this:
String methodName = model.replace("(", "").replace(")", "");
try {
// getMethod() returns only public methods, getDeclaredMethod() returns any visibility
Method method = SerializedExpFamMixture.class.getDeclaredMethod(methodName);
// if the method is not guaranteed to be visible (eg public) you need this:
method.setAccessible(true);
return (SerializedExpFamMixture) method.invoke(null); // how to invoke on the class object
} catch (Exception forBrevity) {
return new SerializedExpFamMixture();
}

Using if-condition or HashMap?

I was asked this question in an interview to improve the code that was provided. The provided code used lot of if statements and therefore I decided to use HashMap as retrieval would be faster. Unfortunately, I was not selected for the position. I am wondering if someone knows a better way than what I did to improve the code?
/* The following Java code is responsible for creating an HTML "SELECT" list of
U.S. states, allowing a user to specify his or her state. This might be used,
for instance, on a credit card transaction screen.
Please rewrite this code to be "better". Submit your replacement code, and
please also submit a few brief comments explaining why you think your code
is better than the sample. (For brevity, this sample works for only 5
states. The real version would need to work for all 50 states. But it is
fine if your rewrite shows only the 5 states here.)
*/
/* Generates an HTML select list that can be used to select a specific U.S.
state.
*/
public class StateUtils {
public static String createStateSelectList() {
return
"<select name=\"state\">\n"
+ "<option value=\"Alabama\">Alabama</option>\n"
+ "<option value=\"Alaska\">Alaska</option>\n"
+ "<option value=\"Arizona\">Arizona</option>\n"
+ "<option value=\"Arkansas\">Arkansas</option>\n"
+ "<option value=\"California\">California</option>\n"
// more states here
+ "</select>\n"
;
}
/* Parses the state from an HTML form submission, converting it to the
two-letter abbreviation. We need to store the two-letter abbreviation
in our database.
*/
public static String parseSelectedState(String s) {
if (s.equals("Alabama")) { return "AL"; }
if (s.equals("Alaska")) { return "AK"; }
if (s.equals("Arizona")) { return "AZ"; }
if (s.equals("Arkansas")) { return "AR"; }
if (s.equals("California")) { return "CA"; }
// more states here
}
/* Displays the full name of the state specified by the two-letter code. */
public static String displayStateFullName(String abbr) {
{
if (abbr.equals("AL")) { return "Alabama"; }
if (abbr.equals("AK")) { return "Alaska"; }
if (abbr.equals("AZ")) { return "Arizona"; }
if (abbr.equals("AR")) { return "Arkansas"; }
if (abbr.equals("CA")) { return "California"; }
// more states here
}
}
My solution
/* Replacing the various "if" conditions with Hashmap<key, value> combination
will make the look-up in a constant time while using the if condition
look-up time will depend on the number of if conditions.
*/
import java.util.HashMap;
public class StateUtils {
/* Generates an HTML select list that can be used to select a specific U.S.
state.
*/
public static String createStateSelectList() {
return "<select name=\"state\">\n"
+ "<option value=\"Alabama\">Alabama</option>\n"
+ "<option value=\"Alaska\">Alaska</option>\n"
+ "<option value=\"Arizona\">Arizona</option>\n"
+ "<option value=\"Arkansas\">Arkansas</option>\n"
+ "<option value=\"California\">California</option>\n"
// more states here
+ "</select>\n";
}
/* Parses the state from an HTML form submission, converting it to the
two-letter abbreviation. We need to store the two-letter abbreviation
in our database.
*/
public static String parseSelectedState(String s) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("Alabama", "AL");
map.put("Alaska", "AK");
map.put("Arizona", "AZ");
map.put("Arkansas", "AR");
map.put("California", "CA");
// more states here
String abbr = map.get(s);
return abbr;
}
/* Displays the full name of the state specified by the two-letter code. */
public static String displayStateFullName(String abbr) {
{
HashMap<String, String> map2 = new HashMap<String, String>();
map2.put("AL", "Alabama");
map2.put("AK", "Alaska");
map2.put("AZ", "Arizona");
map2.put("AR", "Arkansas");
map2.put("CA", "California");
// more state abbreviations here here
String full_name = map2.get(abbr);
return full_name;
}
}
}
I think there are many things wrong with your code, not least the recreation of the Map for each method call.
I would start at the very beginning, with interfaces. We need two things; a State and a StateResolver. The interfaces would look like this:
public interface State {
String fullName();
String shortName();
}
public interface StateResolver {
State fromFullName(final String fullName);
State fromShortName(final String shortName);
Set<? extends State> getAllStates();
}
This allows the implementation to be swapped out for something more sensible at a later stage, like a database. But lets stick with the hardcoded states from the example.
I would implement the State as an enum like so:
public enum StateData implements State {
ALABAMA("Alabama", "AL"),
ALASKA("Alaska", "AK"),
ARIZONA("Arizona", "AZ"),
ARKANSAS("Arkansas", "AR"),
CALIFORNIA("Californiaa", "CA");
private final String shortName;
private final String fullName;
private StateData(final String shortName, final String fullName) {
this.shortName = shortName;
this.fullName = fullName;
}
#Override
public String fullName() {
return fullName;
}
#Override
public String shortName() {
return shortName;
}
}
But, as mentioned above, this can be replaced with a bean loaded from a database. The implementation should be self-explanatory.
Next onto the resolver, lets write one against our enum:
public final class EnumStateResolver implements StateResolver {
private final Set<? extends State> states;
private final Map<String, State> shortNameSearch;
private final Map<String, State> longNameSearch;
{
states = Collections.unmodifiableSet(EnumSet.allOf(StateData.class));
shortNameSearch = new HashMap<>();
longNameSearch = new HashMap<>();
for (final State state : StateData.values()) {
shortNameSearch.put(state.shortName(), state);
longNameSearch.put(state.fullName(), state);
}
}
#Override
public State fromFullName(final String fullName) {
final State s = longNameSearch.get(fullName);
if (s == null) {
throw new IllegalArgumentException("Invalid state full name " + fullName);
}
return s;
}
#Override
public State fromShortName(final String shortName) {
final State s = shortNameSearch.get(shortName);
if (s == null) {
throw new IllegalArgumentException("Invalid state short name " + shortName);
}
return s;
}
#Override
public Set<? extends State> getAllStates() {
return states;
}
}
Again this is self explanatory. Variables are at the instance level. The only dependency on the StateData class is in the initialiser block. This would obviously need to be rewritten for another State implementation but that should be not big deal. Notice this class throws an IllegalArgumentException if the state is invalid - this would need to be handled somewhere, somehow. It is unclear where this would happen but something that needs to be considered.
Finally we implement the required methods in the class
public final class StateUtils {
private static final StateResolver STATE_RESOLVER = new EnumStateResolver();
private static final String OPTION_FORMAT = "<option value=\"%1$s\">%1$s</option>\n";
public static String createStateSelectList() {
final StringBuilder sb = new StringBuilder();
sb.append("<select name=\"state\">\n");
for (final State s : STATE_RESOLVER.getAllStates()) {
sb.append(String.format(OPTION_FORMAT, s.fullName()));
}
sb.append("</select>\n");
return sb.toString();
}
public static String parseSelectedState(final String s) {
return STATE_RESOLVER.fromFullName(s).shortName();
}
public static String displayStateFullName(final String abbr) {
return STATE_RESOLVER.fromShortName(abbr).fullName();
}
}
Notice we only reference the implementation at the top of the utility class, this makes swapping out the implementation quick and painless. We use a static final reference to that the StateResolver is created once and only once. I have also replaced the hardcoded creation of the select with a dynamic loop based one. I have also used a formatter to build the select.
It should be noted that it is never a good idea to build HTML in Java and anyone that does so should have unspeakable things done to them.
Needless to say you should have thorough unit tests against each and every line of the above code.
In short your answer doesn't really come close to a proper, extensible, enterprise solution to the problem at hand. My solution might seem overkill, and you may be right. But I think it's the correct approach because abstraction is key to reusable code.
To avoid manually maintaining 2 maps and keeping them in sync I would just create the second one as the first one inverted. See here on how to do it.
Also as pointed out by others you need to create your maps only once outside of method call.
** Just for fun a way to do it in Scala **
val m = Map("AL" -> "Alabama", "AK" -> "Alaska")
m map { case (k, v) => (v, k) }
// gives: Map(Alabama -> AL, Alaska -> AK)
Everyone seems focused on the parse, but the create can be improved, too. Get all of the state names, sort them alphabetically, and iterate over that collection to create each option. That way, the states used for parsing are always in sync with the states used for cresting. If you add a new state, you only need to add it to the "master" Enum (or whatever), and both methods will reflect the change.
The only mistake you made was to rebuild the map every time around. If you had built the Map just once - perhaps in a constructor I suspect you would have done fine.
public class StateUtils {
class State {
final String name;
final String abbreviation;
public State(String name, String abbreviation) {
this.name = name;
this.abbreviation = abbreviation;
}
}
final List<State> states = new ArrayList<State>();
{
states.add(new State("Alabama", "AL"));
states.add(new State("Alaska", "AK"));
states.add(new State("Arizona", "AZ"));
states.add(new State("Arkansas", "AR"));
states.add(new State("California", "CA"));
}
final Map<String, String> nameToAbbreviation = new HashMap<String, String>();
{
for (State s : states) {
nameToAbbreviation.put(s.name, s.abbreviation);
}
}
final Map<String, String> abbreviationToName = new HashMap<String, String>();
{
for (State s : states) {
nameToAbbreviation.put(s.abbreviation, s.name);
}
}
public String getStateAbbreviation(String s) {
return nameToAbbreviation.get(s);
}
public String getStateName(String abbr) {
return abbreviationToName.get(abbr);
}
}
One thing I don't like about your code is that you create a hashmap each time the method is called. The map should be created just once, at class init time, and referenced from the method.
What you did wrong is what guys are saying - you are creating a new HashMap every time the method is invoked - a static field could rather congaing the data, and populating it only once the class is being loaded my the JVM.
I'd rather use simple switch on strings - the search is not worse than that of HashMap (at least asymptotically) but you don't use extra memory. Though you need two long switches - more code.
But than again HashMap solution the the later one would be the same for me.

how do I access this class

import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
public class LoadSettings
{
public static void LoadMySettings (Context ctx)
{
SharedPreferences sharedPreferences = ctx.getSharedPreferences("MY_SHARED_PREF", 0);
String strSavedMem1 = sharedPreferences.getString("gSendTo", "");
String strSavedMem2 = sharedPreferences.getString("gInsertInto", "");
String cCalId = sharedPreferences.getString("gCalID", "");
setInsertIntoStr(strSavedMem2);
setSendToStr(strSavedMem1);
}
private static String cSendToStr;
private static String cInsertIntoStr;
private int cCalId;
private Uri cCalendars;
public String getSendToStr()
{
return this.cSendToStr;
}
public static void setSendToStr(String pSendToStr)
{
cSendToStr = pSendToStr;
}
public String getInsertIntoStr()
{
return this.cInsertIntoStr;
}
public static void setInsertIntoStr(String pInsertIntoStr)
{
cInsertIntoStr = pInsertIntoStr;
}
}
from the calling class i have tryed lots the current is.
LoadSettings.LoadMySettings(this);
but when i try to get some data for example.
textSavedMem1.setText(LoadSettings.getSendToStr());
i get a Null error.
LoadMySettings is not a class but a method (so it should start with a lower case, if you follow Oracle/Sun's naming conventions for the Java language).
You access it indeed by calling LoadSettings.loadMySettings(someContext), where someContext is the context to pass around. In your example, we don't know what this refers to, so maybe your error lies there.
Then when you do this: textSavedMem1.setText(LoadSettings.getSendToStr());
You call a non-static method, so that should be either using an instance of LoadSettings or, more likely considering your code, you could change getSendToStr to be:
public static String getSendToStr()
{
return cSendToStr;
}
Though that seems to be rather bad design.
Maybe if you tell us more about what you try to do, we can help more, as as such our answers will just take you one step further.
EDIT: Ok, I just figured out what you are trying to do...
You need to go back and learn basic Java concepts and read on access modifiers, and constructors first, and OO semantics in Java in general.
Change your class to this:
public class LoadSettings
{
public LoadSettings(Context ctx)
{
SharedPreferences sharedPreferences =
ctx.getSharedPreferences("MY_SHARED_PREF", 0);
String strSavedMem1 = sharedPreferences.getString("gSendTo", "");
String strSavedMem2 = sharedPreferences.getString("gInsertInto", "");
String cCalId = sharedPreferences.getString("gCalID", "");
setInsertIntoStr(strSavedMem2);
setSendToStr(strSavedMem1);
}
private String cSendToStr;
private String cInsertIntoStr;
private int cCalId;
private Uri cCalendars;
public String getSendToStr()
{
return cSendToStr;
}
public void setSendToStr(String pSendToStr)
{
cSendToStr = pSendToStr;
}
public String getInsertIntoStr()
{
return cInsertIntoStr;
}
public void setInsertIntoStr(String pInsertIntoStr)
{
cInsertIntoStr = pInsertIntoStr;
}
}
And create a new instance of LoadSettings with:
LoadSettings mySettings = new LoadSettings(someContext);
You can then correctly invoke:
textSavedMem1.setText(mySettings.getSendToStr());
Haylem has the right of it, but I just wanted to add a comment:
There are basically two design patterns in Java for what you're trying to do. One is the static class where all the methods and variables are static and you access them as e.g.
LoadSettings.loadMySettings(this);
string = LoadSettings.getSendToStr()
// etc.
The other pattern is the "singleton" class where you create exactly one instance of the class and you access the instance:
LoadSettings ls = new LoadSettings(this);
ls.loadMySettings();
string = ls.getSendToStr();
Either way is good, but what you're doing is a mish-mash of both methods and it won't work.

Categories