I have a number of Enums each of which contain the names of attributes to be tested. The problem I have is how to select the relevant enum for the object. How can I define just a Enum variable which use throughout my code which can be set through an initalise method.
EDIT:
Sorry for the delayed reponse. I had to step away from the desk
It very well be bad design. I have a few enums as follows:
public enum AccountGrpEnum {
Account("Account"),
AccountType("AccountType"),
AcctIDSource("AcctIDSource");
private static Set<String> grpNames = new HashSet<String>(3) {{
for(AccountGrpEnum e : AccountGrpEnum.values()) {
add(e.toString());
}
}};
public static boolean contains(String name) {
return grpNames.contains(name);
}
private String name;
private AccountGrpEnum(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Another Enum:
public enum BlockManValEnum {
avgPx("avgPx"),
quantity("quantity"),
securityIDSource("securityIDSource"),
securityID("securityID"),
blockStatus("blockStatus"),
side("side");
private static Set<String> names = new HashSet<String>(9) {{
for(BlockManValEnum e : BlockManValEnum.values()) {
add(e.toString());
}
}};
public static boolean contains(String name) {
return names.contains(name);
}
private String name;
private BlockManValEnum(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Within my code I am checking the fields of an incoming object to see they are contained within the Enum. As follows:
if (BlockManValEnum.contains(fields[i].getName()))
however I would like it to be along the lines of
if (variableEnum.contains(fields[i].getName()))
Where variableEnum can be set at runtime.
Hope this is clearer guys
Building on previous answers.
enum Color {
RED(1),
GREEN(2),
BLUE(3);
int attrib;
Color(int attribValue) {
attrib = attribValue;
}
public Color getColorForAttrib(int attribValue) {
for(Color c : Color.values()) {
if(c.attrib == attribValue) {
return c;
}
}
throw new IllegalArgumentException("No color could be found for attrib of value " + attribValue);
}
}
...
class SomeClass {
Color c;
public void SomeClass(Color c) {
this.c = c;
}
}
...
class SomeClassUser {
public static void main(String[] args) {
Color c = Color.getColorForAttrib(Integer.valueOf(args[i]));
new SomeClass(c);
}
}
Remember that simplistically, enums are just a class, so you can add any methods you want to them. Whether or not it's a good idea depends on circumstance
Use Enum.valueOf:
Enum<?> variableEnum = AccountGrpEnum.class;
if(Enum.valueOf(variableEnum.getClass(), field[i].getName()) != null) {
doSomething();
}
Since enums are classes and thus can implement interfaces, you could create an interface which holds your contains() method and then implement that method on your enums, then use a generic method which takes a class token of a specific enum type implementing that interface (and which could be set at runtime) to test. Something like this:
CanBeTestedForContains:
public interface CanBeTestedForContains {
boolean contains(String name);
}
ColorEnum:
import java.util.HashSet;
import java.util.Set;
public enum ColorEnum implements CanBeTestedForContains {
R("red"),
B("blue");
private static Set<String> names = new HashSet<String>(3) {
{
for (final ColorEnum e : ColorEnum.values()) {
add(e.name);
}
}
};
private String name;
private ColorEnum(final String name) {
this.name = name;
}
#Override
public boolean contains(final String name) {
return names.contains(name);
}
}
SuitEnum:
import java.util.HashSet;
import java.util.Set;
public enum SuitEnum implements CanBeTestedForContains {
D("diamonds"),
H("hearts"),
C("clubs"),
S("spades");
private static Set<String> names = new HashSet<String>(3) {
{
for (final SuitEnum e : SuitEnum.values()) {
add(e.name);
}
}
};
private String name;
private SuitEnum(final String name) {
this.name = name;
}
#Override
public boolean contains(final String name) {
return names.contains(name);
}
}
ContainsSelectorTest:
public class ContainsSelectorTest {
private static <E extends Enum<E> & CanBeTestedForContains> boolean contains(final Class<E> enumClass, final String name) {
return enumClass.getEnumConstants()[0].contains(name);
}
public static void main(final String[] args) {
if (contains(ColorEnum.class, "red")) {
System.out.printf("%s contains %s\n", ColorEnum.class, "red");
}
if (contains(SuitEnum.class, "hearts")) {
System.out.printf("%s contains %s\n", SuitEnum.class, "hearts");
}
if (contains(SuitEnum.class, "red")) {
System.out.println("This shouldn't happen.");
} else {
System.out.printf("%s DOES NOT contain %s\n", SuitEnum.class, "red");
}
}
}
Output:
class ColorEnum contains red
class SuitEnum contains hearts class
class SuitEnum DOES NOT contain red
Related
I started to programm in Java since Yesterday, and I have the biggest question of my entire programmer life(since Yesterday).
For example, let's say I have a code like this:
public class itsAClass {
static private String A;
public static void main() {
A = "This should be changed";
}
public String something() {
return A;
}
}
I wanted to use the method something() in another Class to get the String Sentence of A, but I got only null.
How can I change the value of A, so that the another Class can get the Value "This should be changed"?
If you just want to bring this code to work you just can make something() static as well.
But this will be not the right way to approach this problem.
If you want to hold code in the main class you could do something like this:
public class AClass {
private String a;
public static void main() {
AClass myC = new AClass();
myC.setA("This should be changed");
// than use myC for your further access
}
public String something() {
return a;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
}
If you want to access it by a external class without direct reference you can checkout the singleton pattern.
public class AClass {
private final static AClass INSTANCE = new AClass();
private String a;
public static void main() {
getSingleton().setA("This should be changed");
}
public String something() {
return a;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public static AClass getSingleton() {
return INSTANCE;
}
}
This way you can access it via AClass.getSingleton() from any location of your code.
You have to call your main() function.
In another class:
itsAClass aClassObj = new itsAClass();
aClassObj.main();
// or rather itsAClass.main() as it is a static function
// now A's value changed
System.out.println(aClassObj.something());
the way to set the value of private variable is by setter and getter methods in class.
example below
public class Test {
private String name;
private String idNum;
private int age;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getIdNum() {
return idNum;
}
public void setAge( int newAge) {
age = newAge;
}
public void setName(String newName) {
name = newName;
}
public void setIdNum( String newId) {
idNum = newId;
}
}
you can call method main() in method something().
public class itsAClass{
static private String A;
public static void main() {
A = "This should be changed";
}
public String something() {
main();
return A;
}
public static void main(String[] args){
itsAClass a1 = new itsAClass();
System.out.println(a1.something());// prints This should be changed
}
}
I have defined an enum in a class A
public class A{
public static final String CANDY = "yelow candy";
public static final String CAKE = "cookie";
public enum Yummy{
CANDY, CAKE;
}
}
In another package,
public class C {
Yummy[] yummies = A.Yummy.values();
for (Yummy yum : yummies){
String yumString = yum.toString();
System.out.println("yum =" + yumString);
}
}
I get CANDY and CAKE as a result, not "yelow candy" and "cookie".
What does I need to change to get the "yelow candy" and "cookie ?
You've defined an enum "A.Yummy" and also two strings, "A.Candy" and "A.CAKE".
They aren't linked at all.
You will want to delete the strings and add something like https://stackoverflow.com/a/13291109/1041364
public enum Yummy {
CANDY("yelow candy"),
CAKE("cookie");
private String description;
private Yummy(String description) {
this.description= description;
}
public String toString() {
return this.description;
}
}
Try the following:
public enum Yummy{
CANDY ("yellow candy"), CAKE ("cookie");
private String name;
private Yummy(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Additional values for enums should be hold in properties. You have to provide constructor to set up those properties.
public enum Yummy {
CANDY("yelow candy"), CAKE("cookie");
private String value;
private Yummy(String value) {
this.value = value;
}
};
And then in code you can use CANDY.value or override toString() method.
Try this:
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
for (Yummy yum : Yummy.values()) {
System.out.printf("%s, %s\n", yum, yum.getValue());
}
}
}
enum Yummy {
CANDY("yelow candy"),
CAKE("cookie");
private String value;
private Yummy(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
In my main class, I have a static method which I pass the array into. It is a static method because if I want to pass something from the main class body to this method, it must be static. In a separate class I have a series of getters and setters (which must be non static ).
How can I pass my static array in and use the non-static getters and setters?
EDIT- In the arraySearch method...I cannot pass in the Person Array and access the getters in the Person Class
public class Main {
public static void main(String[] args) {
Person One = new Person("Alice","Foo", 22, false);
Person Two = new Person("Alice", "Foo",22, false);
Person Three = new Person("Bob","Bar",99, false);
Person Four = new Person("Joe","Blogs",64, false);
Person Five = new Person("Jane", "Joe",42, false);
Person [] People = {One,Two,Three,Four,Five};
printArray(People);
}
public static void printArray(Person [] People)
{
for(int i=0;i<People.length;i++)
{
System.out.println(People[i]);
}
}
public void arraySearch(Person [] People)
{
for(int i=0;i<People.length;i++) //Searches the Array of Objects
{
String firstName = Person.getFirstName();
String secondName=Person.getSecondName();
if((firstName.equals("Joe")&&secondName.equals("B" + //Searches for Joe Blogs and Jane Joe
"logs"))|| ((firstName.equals("Ja" +
"ne")&&secondName.equals("Joe"))))
{
int age=Person.getAge();
Person.setAge(age+1); //Increments Age by 1
}
}
}
}
public class Person {
private String mfirstName;
private String msecondName;
private int mage;
private boolean misRetired;
public Person(String firstName,String secondName,int age, boolean isRetired)
{
mfirstName=firstName;
msecondName=secondName;
mage=age;
misRetired=isRetired;
}
//GETTERS
public String getFirstName()
{
return mfirstName;
}
public String getSecondName()
{
return msecondName;
}
public int getAge()
{
return mage;
}
public boolean getRetired()
{
return misRetired;
}
//SETTERS
public void setFirstName(String firstName)
{
mfirstName=firstName;
}
public void setSecondName(String secondName)
{
msecondName=secondName;
}
public void setAge(int age)
{
mage=age;
}
public void setRetired(boolean isRetired)
{
misRetired=isRetired;
}
//STRING
public String toString()
{
return (mfirstName+"-"+msecondName+"-"+mage+"-"+misRetired);
}
}
This is very basic Java question. You need to create instance of object containing setter/getters from your static method. You can also pass static array in setter of this object. Then you should be able to call those getter/setter methods.
public class Main
{
public static void main(String[] args)
{
MyClass myclass = new MyClass();
myclass.setArgs(args);
System.out.println(myclass.getArgs());
}
}
public class MyClass
{
private String[] args;
public String[] getArgs()
{
return args;
}
public void setArgs(String[] args)
{
this.args= args;
}
}
You have to create an object instance from the class with the getters.
The Amit answer is correct; this just has some more info and more closely matches the situation you describe in your question.
Your basic premise "It is a static method because if I want to pass something from the main class body to this method, it must be static." is wrong. The method to which you pass the array does not need to be static. Here is some code:
public final class Main
{
private static final String[] staticOTron =
{
"one",
"two",
"three"
};
public static void main(final String[] args)
{
String[] hootBerrySause;
Tool tool = new Tool();
tool.setStaticOTron(staticOTron);
hootBerrySause = tool.getStaticOTron();
for (String value : hootBerrySause)
{
System.out.println("Value: " + value);
}
}
}
// this can be in a different file.
public final class Tool
{
private static String[] staticOTron;
public void setStaticOTron(final String[] newValue)
{
staticOTron = newValue;
}
public String[] getStaticOTron()
{
return staticOTron;
}
}
Sunil kumar from vmoksha
Your asking deeper navigation
Just create the instance of particular or create the getter &and setter in the main
class
I have a few Java enums as such
public enum Aggregation
{
MORTGAGE( "Mortgage" ),
POOLS( "Pools" ),
PORTFOLIO( "Portfolio" );
private Aggregation( final String name )
{
m_Name = name;
}
private String m_Name;
static Map< String, Aggregation > c_LOOKUP =
new HashMap< String, Aggregation >();
static {
for (Aggregation agg:values()){
c_LOOKUP.put(agg.m_Name,agg);
}
}
public Aggregation lookup(String name){
return c_LOOKUP.get( name );
}
#Override
public String toString()
{
return m_Name;
}
}
public enum Interval
{
MONTHLY( "Monthly" ),
QUARTLY( "Quartly" ),
SEMIANNUALLY( "SemiAnnually" ),
ANNUALLY("Annually");
private Interval( final String name )
{
m_Name = name;
}
private String m_Name;
static Map< String, Interval > c_LOOKUP =
new HashMap< String, Interval >();
static {
for (Interval agg:values()){
c_LOOKUP.put(agg.m_Name,agg);
}
}
public Interval lookup(String name){
return c_LOOKUP.get( name );
}
#Override
public String toString()
{
return m_Name;
}
}
As you can see, there are quite some code duplication here. It would be nice if there is a way to introduce something like an abstract common ancestor class. But java enum cannot inherent. What would be the best approach? Thanks.
Edit:
I have work out a version similar to ĆukaszBachman and missingfacktor
static public enum Aggregation
{
MORTGAGE( "Mortgage" ),
POOLS( "Pools" ),
PORTFOLIO( "Portfolio" );
private final String m_Name;
final static private ReverseDictionary< Aggregation > c_DICTIONARY =
new ReverseDictionary< Aggregation >( Aggregation.class );
static public Aggregation lookup( final String name )
{
return c_DICTIONARY.lookup( name );
}
private Aggregation( final String name )
{
m_Name = name;
}
#Override
public String toString()
{
return m_Name;
}
}
static public enum Interval
{
MONTHLY( "Monthly" ),
QUARTLY( "Quartly" ),
SEMIANNUALLY( "SemiAnnually" ),
ANNUALLY( "Annually" );
private final String m_Name;
final static private ReverseDictionary< Interval > c_DICTIONARY =
new ReverseDictionary< Interval >( Interval.class );
static public Interval lookup( final String name )
{
return c_DICTIONARY.lookup( name );
}
private Interval( final String name )
{
m_Name = name;
}
#Override
public String toString()
{
return m_Name;
}
}
static public class ReverseDictionary< E extends Enum< E >>
{
Map< String, E > c_LOOKUP = new HashMap< String, E >();
public ReverseDictionary( final Class< E > enumClass )
{
for( final E agg : EnumSet.allOf( enumClass ) )
{
c_LOOKUP.put( agg.toString(), agg );
}
}
public E lookup( final String name )
{
return c_LOOKUP.get( name );
}
}
I see some reasoning. However, it is still not very satisfactory.
It is hard to define the interface for lookup(String) because of the different return type
I can appreciate that the lookup(String) is not really duplication but a specification, but I am still feel that m_Name field and the toString() logic is a bit redundant. We are really specifying one category of enum, and it seems to be "is-a" relationship in my opinion.
Favor composition over inheritance and programming for the sake of interfaces. Since Enums are classes (not regular, but still - classes) you can create some field containing shared logic, let the enum implement you interface and delegate implementation to this field.
Relevant code snippets:
Shared interface
public interface MyInterface {
void someMethod();
}
Logic implementation
public class MyInterfaceImpl implements MyInterface {
public void someMethod() {
System.out.println("Do smth...");
}
}
First enum
public enum EnumA implements MyInterface {
;
private MyInterface impl = new MyInterfaceImpl();
public void someMethod() {
impl.someMethod();
}
}
Second enum
public enum EnumB implements MyInterface {
;
private MyInterface impl = new MyInterfaceImpl();
public void someMethod() {
impl.someMethod();
}
}
Please do note that EnumA and EnumB are not really code duplication, since that is plain delegation (valid, in my opinion). Also please note that everything is nicely glued together by using interface.
Here is how you can solve your problem with composition and delegation. (I think this is the DRYest you can get with Java, for the case in hand.)
import java.util.*;
interface HasName {
public String getName();
}
class EnumEnhancer<E extends Enum<E> & HasName> {
private Map<String, E> lookup;
public EnumEnhancer(E... values) {
lookup = new HashMap<String, E>();
for (E e : values) {
lookup.put(e.getName(), e);
}
}
public E lookup(String name) {
return lookup.get(name);
}
public String toString(E e) {
return e.getName();
}
}
enum Color implements HasName { // This is interface inheritance.
RED("red"), GREEN("green"), BLUE("blue");
// This is composition.
private static final EnumEnhancer<Color> enhancer =
new EnumEnhancer<Color>(values());
private String name;
private Color(String name) {
this.name = name;
}
public String getName() {
return name;
}
// This is delegation.
public String toString() {
return enhancer.toString(this);
}
// This too is delegation.
public static Color lookup(String name) {
return enhancer.lookup(name);
}
}
class Main {
public static void main(String[] args) {
System.out.println(Color.lookup("blue")); // prints blue
}
}
You can achieve this with Java 8 default interface methods:
public class test
{
public static void main (String[] arguments) throws Exception
{
X.A.foo ();
Y.B.foo ();
}
}
interface MyEnumInterface
{
String getCommonMessage ();
String name ();
default void foo ()
{
System.out.println (getCommonMessage () + ", named " + name ());
}
}
enum X implements MyEnumInterface
{
A, B;
#Override
public String getCommonMessage ()
{
return "I'm an X";
}
}
enum Y implements MyEnumInterface
{
A, B;
#Override
public String getCommonMessage ()
{
return "I'm an Y";
}
}
Note that the interface doesn't know it will be implemented by enums, so it cannot use Enum methods on this in the default methods. However, you may include those methods in the interface itself (like I did with name()) and then use them normally. They will be "implemented" for you by Enum when you declare an enumeration.
How about a static helper class that holds your common functions, call them from your enum methods.
In regards to your comment about toString().
public enum MyEnum{
ONE("one");
public MyEnum(String m_Name){
this.m_Name = m_Name;
}
public String toString(){
return m_Name;
}
String m_Name;
}
just define your common behviur in the First class:
public class First {
public String name() {
return "my name";
}
...
}
and than extend it in each class:
public SecondClass extends First {
...
}
I have a question concerning Json deserialization using Jackson.
I would like to deserialize a Json file using a class like this one:
(taken from http://wiki.fasterxml.com/JacksonInFiveMinutes)
public class User
{
public enum Gender { MALE, FEMALE };
public static class Name {
private String _first, _last;
public String getFirst() { return _first; }
public String getLast() { return _last; }
public void setFirst(String s) { _first = s; }
public void setLast(String s) { _last = s; }
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
A Json file can be deserialized using the so called "Full Data Binding" in this way:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
My problem is the usage of the inner class "Name". I would like to do the same thing without using inner classes. The "User" class would became like that:
import Name;
import Gender;
public class User
{
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
This means to find a way to specify to the mapper all the required classes in order to perform the deserialization.
Is this possible? I looked at the documentation but I cannot find any solution.
My need comes from the fact that I use the Javassist library to create such classes, and it does not support inner or anonymous classes.
Thank you in advance
There should be no difference between the static inner class Name, and the top-level class of the same name. The Jackson runtime should not be able to meaningfully distinguish between the two situations.
Have you tried moving the Name class out of User, changing it into a top-level class? It should still work as before.
edit: I just tried this, and it works fine when Name is a top-level class. The example had it as an inner class for the sake of brevity, I suspect.
mr. Skaffman's answer is right on. The only additional thing to mention is that unlike JAXB, Jackson does not generally require you to specify classes you operate on, except for the root class (and not always even that, if you use Polymorphic Handling).