How to use arguments in cloned object? - java

So let say I have such prototyping:
private static Hashtable<String, Furniture> map =
new Hashtable<String, Furniture>();
public My_product() {
loadCache();
}
public My_Product createProduct(String type, String name) {
Furniture cachedproduct = map.get(type);
return (Furniture) cachedproduct.clone();
}
private static void loadCache() {
Sub_product1 pr1 = new Sub_product1(null);
map.put("pr1", pr1);
Sub_product2 pr2 = new Sub_product2(null);
map.put("pr2", pr2);
}
So when I make an instance of an object, I don't know what value will be entered after cloning it (creating object using cloning). So I chosen null value for object instance. But when I clone it then I know what value needs to be assigned for that object. So how could I specify while cloning to put some value instead of null one from object instance?
As you can see in method createProduct method, there is argument called name. I would like that name to be used in cloned object, but how could I do that?

Can you use setter methods?
public My_Product createProduct(String type, String name) {
Furniture cachedproduct = map.get(type);
Furniture clonedProduct = (Furniture) cachedproduct.clone();
clonedProduct.setType(type);
clonedProduct.setName(name);
return clonedProduct;
}
However, I'm still not clear on the whole idea of this cloning of cached objects from the map. Is your product instantiation very expensive? What's the trick?

You cannot pass arguments through the Java built-in clone mechanism. You could provide a setter on the Furniture class to change the name after it has been cloned.
Note that cloning in Java is generally considered broken. It is a brittle way to create objects. Generally you are better of using the factory pattern, e.g. something like:
interface FurnitureBuilder {
Furniture build(String name);
}
class SubProduct1Builder implements FurnitureBuilder {
public Furniture build(String name) { return new SubProduct1(name); }
}
class MyFurnitureFactory {
private final Map<String, FurnitureBuilder> builderByType = ...
// initialization omitted
public Furniture create(String type, String name) {
return builderByType.get(type).build(name); // null check omitted!
}
}

Related

Failure "field should be initialised with an implementing instance of the interface"?

public class Player implements Comparable<Player> {
//Fields
private Name name;
private Rollable rollable;
//Constructors
public Player() {
name = new Name();
rollable = new Rollable();
}
public Player(Name name) {
this.name = name;
rollable = new Rollable();
}
public Player(Name name, Rollable rollable) {
this.name = name;
this.rollable = rollable;
}
Hello, for my constructors where i have put rollable = new Rollable(); I am getting an error which states that it Cannot instantiate the type rollable.
Below i have added the JUnit test and i will also add the code for the Rollable class
#Test
public void testDefaultConstructor() {
Player p = new Player();
assertEquals("Name field should be initialised with a default Name object ", new Name(), p.
getName());
assertTrue("Player's rollable field should be initialised with an. implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
#Test
public void testCustomConstructor1arg() {
Name n = new Name("Joe", "Bloggs");
Player p = new Player(n);
assertSame("Player's name field should be initialised with and return the same object received by the constructor", n, p.getName());
assertTrue("Player's rollable field should be initialised with an implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
Now below is the JUnit test for the default constructor whcih is also giving me the failure of Players rollable field should be initialised with an implementing instance of the Rollable interface, however, all of my other JUnit tests are passing.
#Test
public void testDefaultConstructor() {
Player p = new Player();
assertEquals("Name field should be initialised with a default Name object ", new Name(), p.getName());
assertTrue("Player's rollable field should be initialised with an implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
The code for my Rollable class is as below;
public interface Rollable {
public void roll();
public int getScore();
}
The methods for my rollable code are as below;
//Methods
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
public Rollable getRollable() {
return rollable;
}
public void rollDice() {
rollable.roll();
}
public int getDiceScore() {
return rollable.getScore();
}
All help will be appreciated as i am struggling with the failures, thank you.
Your getRollable() method is:
public Rollable getRollable() {
return rollable;
}
So, if you call that from a constructor, for example:
public Player() {
name = new Name();
rollable = getRollable();
}
then rollable will be assigned the value of rollable, which is by default null.
As such, when you call getRollable() again in the test, you get back the value you assigned to the field - null - and by definition - null instanceof Rollable is false.
Instead, you need to create a new instance of Rollable, for example:
rollable = new Rollable();
(Don't know if it is directly instantiable. You've not provided the declaration of the Rollable class).
Your Rollable is an interface, and in Java you can only create instances of non-abstract classes.
So you need to write at least one class that implements Rollable. Of this class, you can create instances.
Why is that so?
Have a look at e.g. the Comparable interface (serving me as an analogon to your Rollable). Comparable denotes classes that support some kind of greater / equal / less than comparison, by requiring the class to have a method named compareTo(). If you were to instantiate a Comparable, what would you expect to be the result? A String, a Long, a Double or what? And the same applies to your Rollable.
An interface defines some requirements that implementing classes must fulfill, but they don't denote classes themselves, so you can't create (direct) instances of interfaces.

Method Overloading; Naming Helper Method

I like creating public helpers for private members when creating functions. I made a public helper
public void create(String key, String value) { ... }
for a private member
private void create(String key, String value) { ... }
Now, I am overloading the private member and know I need to do so in Java by
Method signature (type or quantity)
and I am unable to overload by return type. Thus, I decide to modify my private member to accept a boolean argument.
private void create(String key, String value, boolean status) { ... }
I admit this parameter is not one I plan to use or consider. Have I become complacent to accept poor coding behavior?
The public helper merely calls the private member passing supplied arguments
public void create(String key, String value) { create(key, value, true); }
While a helper class might be a quick solution, you are still coupling the implementation to the classes you are exposing (the "caller" class). Interfaces were created to create the abstraction you intend to create (i.e. hiding private implementation from public view) but the added flexibility that:
Could be used by other classes wanting to have their own implementations of similar behaviour
De-couples the implementation from the calling class.
At run-time you could choose which implementation to use (via IoC or similar)
Here's my suggestion:
MyObjectImpl.java -> implements MyObject.java
private Object createObjectNotInitialized( String name ){
return new Object();
}
private Object createObjectInitialized( String name ){
Object newObj = new Object();
newObj.setName( name );
return newObj;
}
public Object createObject( String name, boolean doInit ){
if( doInit ){
return createObjectInitialized(name);
}else{
return createObjectNotInitialized(name);
}
}
// you can chose to init objects by default - I chose not to for this example
public Object createObject( String name ){
return createObjectNotInitialized(name);
}
MyObject.java -> Interface
Object createObject( String name, boolean doInit );
Object createObject( String name );
Caller.java Calling Class
MyObject myObj = new MyObjectImpl();
Object o = myObj.createObject( "Hello" );

How can I iterate through a TreeMap and use reflection to get a subclass name?

Suppose I had the following abstract class and two subclasses:
public abstract class Contact {
private String name;
public void showDetails() {
System.out.println(name);
}
}
public class Personal extends Contact {
private String relationship;
// #override
public void showDetails() {
System.out.println(name);
System.out.println(relationship);
}
}
public class Business extends Contact {
private String company;
// #override
public void showDetails() {
System.out.println(name);
System.out.println(company);
}
}
Also suppose that I have a TreeMap containing integers as keys and either Business objects or Personal objects as values:
Map<Integer, Contact> masterList = new TreeMap<Integer, Contact>();
masterList.put(1, bContact1);
masterList.put(2, bContact2);
masterList.put(3, pContact1);
masterList.put(4, pContact2);
Is it possible to iterate through the TreeMap AND use reflection to see what subclass each object belongs to, in order to use the correct overriding method?
For example, key 1 is paired with bContact1, which is a Business object. I want to use the showDetails() method from the Business subclass for this particular value.
I can iterate through the map just fine, but I'm having trouble with the reflection part. Any help is appreciated!
You don't need reflection, you need polymorphism. Just call the method on the object, Java will do the rest to invoke the proper implementation.
Contact contactRef = masterList.get(2);
contactRef.showDetails(); // overriden method invoked if it exists, inherited otherwise

Read only objects produced by a factory in Java

In previous C++ code I've used friend classes when creating a factory that can output "read only" objects which means that as the objects are consumed throughout the code there is no risk that they can be inadvertently changed/corrupted.
Is there is there a similar way to implement this in Java or am I being overly defensive?
Make use of the final keyword. This keyword can mark a class/methods as non-extendable, and mark fields/variables as non-mutable.
You will hide the default constructor of the object using the private constructor, and force parameterised constructors which will initialise all necessary final fields.
Your only problem is that the factory is kind of redundant. Since all fields of the object are final, you will have to use all factory methods at object build-time.
Example:
public final class DataObject
{
protected final String name;
protected final String payload;
private DataObject()
{
}
public DataObject(final String name, final String payload)
{
this.name = name;
this.payload = payload;
}
}
// Using the factory
DataObject factory = new Factory().setName("Name").setPayload("Payload").build();
// As opposed to
DataObject dao = new DataObject("Name", "Payload");
// ==> Factory becomes redundant, only adding extra code
Solution without final:
I'm afraid you will have to forget about the immutability mechanism of C++. The factory pattern is never a bad choice if you have huge data objects (i.e. with a lot of setters), but you can't really avoid mutability of the constructed object. What you could do, is make the data object an inner class of the factory, and make the setters private. That way, ONLY the factory can access the setters. This would be the best approach for you (i.e. simulate immutability).
Example:
public class Factory
{
private String name;
private String payload;
public Factory setName(final String name)
{
this.name = name;
}
public Factory setPayload(final String payload)
{
this.payload = payload;
}
public DataObject build()
{
DataObject newObj = new DataObject();
newObj.setName( this.name );
newObj.setPayload( this.payload );
return newObj;
}
public class DataObject
{
// fields and setters, ALL PRIVATE
}
}
You can either put the object class and factory in the same package, and make the mutable methods package-scoped (this is the default visibility in Java, simply don't declare the methods to be public, private or protected), or make the class truly immutable and do all the work in the constructor. If you find that there are too many arguments in the constructor and it is difficult to understand, consider the Builder Pattern.
There is no direct equal to friend classes in Java. However have a look at http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html.
If your object implements an interface and the factory returns interface type rather than the concrete type (which is better) then you can use java.lang.reflect.Proxy to create dynamic proxy at runtime that intercepts all method calls to the target object. As in the following code example FooFactory class creates a Foo instance (every time its createFoo method is called) but does not directly return instance but instead returns a dynamic proxy that implements the same interface as Foo and dynamic proxy intercepts and delegates all method calls to the Foo instance. This mechanism can be helpful to control access to a class when you dont have class code.
public class FooFactory {
public static IF createFoo() {
//Create Foo instance
Foo target = new Foo(); // Implements interface IF
//Create a dynamic proxy that intercepts method calls to the Foo instance
IF fooProxy = (IF) Proxy.newProxyInstance(IF.class.getClassLoader(),
new Class[] { IF.class }, new IFInvocationHandler(target));
return fooProxy;
}
}
class IFInvocationHandler implements InvocationHandler {
private Foo foo;
IFInvocationHandler(Foo foo) {
this.foo = foo;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (method.getName().equals("setMethod")) {
// Block call
throw new IllegalAccessException();
} else {
// Allow call
method.invoke(proxy, args);
}
return null;
}
}
class Foo implements IF {
public void setMethod() {
} // method that is not allowed to call
public void getMethod() {
}
}
interface IF {
void setMethod(); // method that is not allowed to call
void getMethod(); // method that is allowed to call
}
The closest thing to a C++ friend class in Java is package-private access.
SomeObject.java:
package somewhere.someobjandfriends;
public class SomeObject {
Object aField; // field and constructor
SomeObject() {} // are package-only access
public void aMethod() {
System.out.println(this);
}
}
SomeObjFactory.java:
package somewhere.someobjandfriends;
public class SomeObjFactory {
public SomeObject newHelloWorld() {
return new SomeObject() {
{
aField = "hello world!";
}
#Override
public String toString() {
return aField.toString();
}
};
}
}
Anywhere outside of the package can see SomeObject and aMethod but can only create new instances through the factory.

Java Initialization/Declaration of Objects

I have an object, obj, of type MyObject, that I declare an instance of.
MyObject obj;
However, I don't initialize it. MyObject's Class looks something like:
public class MyObject {
public String i;
public String j;
public MyObject(String i) {
i = this.i;
}
}
So now, I want to set the value of j. So I say:
obj.j = "Hello";
Can I do this without having initialized obj? i.e. without saying:
obj = new MyObject("My i");
Will this object be null if I were to check the value of it, if I don't initialize it, or is setting a field within it enough to make it not null?
Thanks!
No, you cannot do that. You will have to create a new instance of MyObject if you want to access its fields.
Unless you make the fields static, ofcourse.
Do note that having your fields public violates encapsulation. You should make them private (or protected, if it's appropriate) and use getters and setters to provide access.
Sidenote:
public MyObject(String i) {
i = this.i;
}
This will not do what you want.
You have to assign the parameter i to the field variable i, not the other way around.
public MyObject(String i) {
this.i = i;
}

Categories