Call on different constructor with 'default' HashMap - java

I had a lot of testcases running on the class MyClass, using it's default constructor: MyClass().
Now the requirements of MyClass changed and the user can provide a HashMap to indicate some pairs . Now a MyClass needs to have at least one pair and throws exceptions if one of those is null.
I was hoping to create another default constructor to avoid having to rewrite all the test methods something like:
public MyClass() {
HashMap<KeyClass, ValueClass> hashMap = HashMap<KeyClass, ValueClass>();
hashMap.put(KeyClass.someValue, new ValueClass());
this(hashMap);
}
Now this doesn't work, because i have to call the other constructor first, so i thought of writing some method
private static HashMap<KeyClass, ValueClass> getDefaultHashmap();
and using it to call the other constructor like this:
public MyClass() {
this(MyClass.getDefaultHashmap());
}
But this seemed to me as not really good style, so i was hoping you could tell me what the right way to do something like this is!

You could inline the HashMap creation:
public MyClass() {
this(new HashMap<KeyClass, ValueClass>() {{
put(KeyClass.someValue, new ValueClass());
}});
}
But you'd have to ignore the serial-id warning to keep it "pretty".

Personally, I would go with creating a new HashMap(...) in both constructors, and not try to wrap the creation in a new static method.

Here's the solution that I typically use:
public MyClass {
private static Map<KeyClass, ValueClass> newMap() {
Map<KeyClass, ValueClass> result = new HashMap<KeyClass, ValueClass>();
result.put(KeyClass.someValue, new ValueClass());
return result;
}
public MyClass() {
this(newMap());
}
public MyClass(Map<KeyClass, ValueClass> m) { ... }
}
I prefer it over subclassing the HashMap-class (as suggested by #alpian) - Seems cleaner, and also does not create the risk of breaking the contract of the equals() method (described here: http://c2.com/cgi/wiki?DoubleBraceInitialization)

If you want to avoid creating a new anonymous HashMap subclass, and only need one pair, and don't want to make a new static method, you could do this:
public MyClass() {
this(new HashMap<KeyClass, ValueClass>(
Collections.singletonMap(KeyClass.someValue, new ValueClass())));
}
If your other constructor takes a Map and copies it, you may not even need to crate the HashMap
public MyClass() {
this(Collections.singletonMap(KeyClass.someValue, new ValueClass()));
}

Related

What is the Java best practice to initialize a class with many optional data members?

I'm migrating a project from C# to Java.
I have many classes, which have a lot of properties and the user can set any subset of them.
So to initialize the class I provide an empty constructor and the user can initialize any property using the C# initialization list as following:
var a = new MyClass() { Prop1 = "something", Prop2 = 8, Prop15 = new Point(2,3) };
What is the best practice for such a case in Java?
I've seen the following syntax:
MyClass a = new MyClass(){
{
setProp1("Something");
setProp2(8);
setProp15(new Point(2,3));
}
};
However, I understand this is a lot more than a syntactic sugar, it actually creates an anonymous class and places all the methods in the initialization block of the new class.
So I'm not sure that it is the recommended way to initialize such a class.
What is the recommendation for such a case?
You have to create POJO for your class and then initialize it field by using it's setter method.
class MyClass{
Prop1 = null;
Prop2 = null;
// getter and setter method
}
I like to use a definition class.
public class VehicleDef
{
int wheels;
Color color;
Brand brand;
Type type;
int cylinderVolume;
....
}
Now, you can create a constructor that takes this VehicleDef class as an argument:
public class Vehicle
{
// all props here:
public Vehicle (VehicleDef def)
{
// set properties and do stuff
}
}
Now, you can use it like this:
VehicleDef def;
def.wheels = 4;
def.color = Color.RED;
def.brand = Brands.HONDA;
def.type = VehicleTypes.CAR;
def.cylinderVolume = 400;
Vehicle vehicle = new Vehicle(def);
Having an object of an anonymous subclass isn't that bad usually. It only becomes a problem when you use constructs like if (object.getClass() == MyClass.class) but these shouldn't really be necessary when you write proper object-oriented code. Better use if (object instanceof MyClass) which is also true for subclasses of MyClass or even better put any class-specific code into the class itself.
An alternative way to initialize an object with many attributes is to use the Builder pattern.
Create a public class nested inside MyClass which has the purpose to create an instance of MyClass. Because it is nested inside MyClass it can access all the private fields of the instance it is initializing. Using such a builder could look like this:
MyClass a = new MyClass.Builder().setProp1("Something")
.setProp2(8)
.setProp15(new Point(2,3))
.build();
This example uses a builder with a fluent interface: All setters return this which allows you to chain method-calls with a simple . between them.
Without double-brace-initialization:
MyClass a = new MyClass();
a.setProp1("Something");
a.setProp2(8);
a.setProp15(new Point(2,3));
This is the way to go if the number of (mutable) properties is large.
When some properties are immutable (final), adding a specific constructor is necessary.
Any number of additional constructors can be added to pass properties at construction time (if possible, also add a default constuctor with no args):
public class MyClass {
// default constructor
public MyClass() {
}
// convenience constructor
public MyClass(String s, int i, Point p) {
setProp1(s);
setProp2(i);
setProp15(p);
}
}

Java Map of References to Singletons

I'd like to create a map of singleton classes that I can access via a cross reference in order to respond to a specific request. I have the following implemented, but having trouble getting to an actual reference that I can call getInstance() on.
Map<Integer, Class<? extends Thing>> xref = new HashMap<Integer, Class<? extends Thing>>();
xref.put(1, ThingOne.class);
xref.put(2, ThingTwo.class);
Class<? extends Thing> t = xref.get(1);
Ultimately then do something like...
something.perform(arg1, arg2);
Can't figure out how to get from "t" to "something", or if that's possible given the way I have it coded. I tried calling .cast(Thing.class).getInstance(), but got a Cast exception. Also tried reflection to get the getInstance() method, but no luck there either.
It may be I'm going down the wrong path altogether. Given 1..n possible functions, any given instance of the solution may only require a subset of these. In addition, I'd like to easily add/delete classes and manage the interface through config vs. a bunch of object instantiations at startup time.
Thanks!!!
I don't quite understand your purpose in creating this map. From what you've written, it seems you could simply put static getInstance() methods, that return singletons, on each relevant class. Or even more trivial: put each shared instance as a static final field of its class.
If you must use a map, don't use an integer as a key. The class is the key, and its instance is the value. Something like:
private static final Map<Class<?>,Object> singletons = new HashMap<>();
public static synchronized <T> T getSingleton(Class<T> klass) {
Object obj = singletons.get(klass);
if (obj == null) {
try {
obj = klass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
singletons.put(klass, obj);
}
return klass.cast(obj);
}
The creation code there is icky and requires a public no-arg constructor. You could alternatively call via reflection a static, specifically named method on each class to create the desired instance ("createInstance"), which might be a bit more flexible, but when you do that, it once again asks why bother with the map, when you could call a method on the class directly?
One interesting possibility with the map is to supply functions to create instances. In Java 8 syntax (import java.util.function.Supplier):
private static final Map<Class<?>,Object> singletons = new HashMap<>();
public static synchronized <T> T getSingleton(Class<T> klass) {
Object obj = singletons.get(klass);
if (obj instanceof Supplier) {
obj = ((Supplier<?>)obj).get();
singletons.put(klass, obj);
}
return klass.cast(obj);
}
public static synchronized <T> void declareSingleton(Class<T> klass, Supplier<T> supplier) {
if (Supplier.class.isAssignableFrom(klass)) {
// prevent Supplier<Supplier<?>> weirdness;
// could use separate maps if those are really needed
throw new UnsupportedOperationException();
}
singletons.put(klass, supplier);
}
static {
// add creation expressions for several classes;
// instances will not be created until needed
declareSingleton(ThingOne.class, () -> new ThingOne());
declareSingleton(ThingTwo.class, () -> new ThingTwo(123));
}
I'm not sure if this is what you want but it might contain some ideas.
Edit: I've just realized a problem of using the Class itself as a key: it causes the class to be loaded even if it is not needed during a particular program run. Using a String key would avoid loading unneeded classes, but increases fragility. This is another argument against using a map for all this.

How to Avoid Constructor calling During Object Creation?

I want to avoid the constructor calling during object creation in java (either default constructor or user defined constructor) . Is it possible to avoid constructor calling during object creation???
Thanks in advance......
Simply extract the intialization logic that you want to avoid into another method called init. You can not avoid calling exactly one constructor.
No matter what pattern or strategy you use, at some point your will need to call a constructor if you want to create an object.
Actually, its possible under some circumstances by using classes from the JVM implementation (which do not belong to the JRE API and are implemenation specific).
One example here http://www.javaspecialists.eu/archive/Issue175.html
It should also be possible using sun.misc.Unsafe.allocateInstance() (Java7)
Also, the constructor is apparently bypassed when using the clone()-method to create a copy of an object (and the class doesn't override clone to implement it different from the Object.clone() method).
All of these possibilities come with strings attached and should be used carefully, if at all.
You can mock the constructors of a class. They will still be called, but not executed. For example, the following JUnit+JMockit test does that:
static class CodeUnderTest
{
private final SomeDependency someDep = new SomeDependency(123, "abc");
int doSomething(String s)
{
someDep.doSomethingElse(s);
return someDep.getValue();
}
}
static final class SomeDependency
{
SomeDependency(int i, String s) { throw new RuntimeException("won't run"); }
int getValue() { return -1; }
}
#Test
public void mockEntireClassIncludingItsConstructors()
{
new NonStrictExpectations() {
#Mocked SomeDependency mockDep;
{ mockDep.getValue(); result = 123; }
};
int result = new CodeUnderTest().doSomething("testing");
assertEquals(123, result);
}

Java - Class type from inside static initialization block

Is it possible to get the class type from inside the static initialization block?
This is a simplified version of what I currently have::
class Person extends SuperClass {
String firstName;
static{
// This function is on the "SuperClass":
// I'd for this function to be able to get "Person.class" without me
// having to explicitly type it in but "this.class" does not work in
// a static context.
doSomeReflectionStuff(Person.class); // IN "SuperClass"
}
}
This is closer to what I am doing, which is to initialize a data structure that holds information about the object and its annotations, etc... Perhaps I am using the wrong pattern?
public abstract SuperClass{
static void doSomeReflectionStuff( Class<?> classType, List<FieldData> fieldDataList ){
Field[] fields = classType.getDeclaredFields();
for( Field field : fields ){
// Initialize fieldDataList
}
}
}
public abstract class Person {
#SomeAnnotation
String firstName;
// Holds information on each of the fields, I used a Map<String, FieldData>
// in my actual implementation to map strings to the field information, but that
// seemed a little wordy for this example
static List<FieldData> fieldDataList = new List<FieldData>();
static{
// Again, it seems dangerous to have to type in the "Person.class"
// (or Address.class, PhoneNumber.class, etc...) every time.
// Ideally, I'd liken to eliminate all this code from the Sub class
// since now I have to copy and paste it into each Sub class.
doSomeReflectionStuff(Person.class, fieldDataList);
}
}
Edit
I picked the accepted answer based on what applied best to my problem, however it seems to me that all three of the current answers have their merits.
No, it's not possible without grabbing the stacktrace (which is imo nastier than your initial approach and for which I would in any way prefer Thread#getStackTrace() above new Exception()).
Rather do that job in a non-static initializer (or the default constructor) of the abstract class where you check the initialized status.
public abstract class SuperClass {
{
if (!isInitialized(getClass())) {
initialize(getClass());
}
}
}
The called methods in turn can be safely static.
yes, I use this often to initialize a static Log variable :
e.g. :
public class Project implements Serializable, Cloneable, Comparable<Project> {
private static final Logger LOG = LoggerFactory.getLogger(Project.class);
...
To get a class at runtime, you could do something along the lines of
public class Test {
public static void main(String[] args) {
try{
throw new Exception();
}
catch(Exception e){
StackTraceElement[] sTrace = e.getStackTrace();
// sTrace[0] will be always there
String className = sTrace[0].getClassName();
System.out.println(className);
}
}
}
Not pretty but will do the job (ripped from http://www.artima.com/forums/flat.jsp?forum=1&thread=155230).
This means you still make a call from the subclass (so is in the stack trace), but you don't need to include the XXX.class as an argument.

Is there a difference between these two initialisation modes?

Let's say I have this:
public class Whatever {
private ArrayList<String> myList = new ArrayList<String>();
// more code goes here
}
or let's say I have this:
public class Whatever {
private ArrayList<String> myList = null;
public Whatever() {
myList = new ArrayList<String>();
}
}
What's the difference between these two initialisations of myList? Would it be wrong to preffer the first variant?
The first variant will always instantiate the array list, the second one only when calling the default constructor. Meaning for the second solution you will have to call the default constructor for any additional constructor you add e.g.
public class Whatever {
private final List<String> myList;
public Whatever() {
myList = new ArrayList<String>();
}
public Whatever(String name) {
this();
// Other stuff done
}
public Whatever(List<String> myList) {
this.myList = myList;
}
}
The (second) "lazy" initialization method might be better if you don't always use the list (e.g. if you set the list in another constructor directly like in my example) and want to avoid creating unnecessary objects. (EDIT: I changed the ArrayList to an interface and set it final. It wasn't part of the question but it is - as mentioned in the comments - the best way to use List collections).
The JVM first executes code such as this (outside the constructor):
public class Whatever {
private ArrayList<String> myList = new ArrayList<String>();
// more code goes here
}
And only then code such as this (inside the constructor):
public class Whatever {
private ArrayList<String> myList = null;
public Whatever() {
myList = new ArrayList<String>();
}
}
So unless the order of execution is somehow important to you i guess #Daff's answer is the right one.
In this particular example, there is no difference except that the first form is shorter.
However, if the attribute initialization expression (potentially) throws exceptions, the second form allows you to catch the exceptions, or declare them as thrown in the constructor signature.
And of course, if you have multiple constructors, the second form allows you to initialize the attribute differently in each constructor ... or use constructor chaining to initialize the attribute the same ... or mix the two styles of initialization.

Categories

Resources