Java cloning abstract objects - java

I'm wondering if there is any way to do the following. I have an abstract class, Shape, and all its different subclasses and I want to override the clone method. All I want to do in the method is create a new Shape from the toString() of the current one. Obviously I can't do the following because Shape is abstract. Is there another way to do this because overriding clone in every subclass just for a simple name change seems useless.
public abstract class Shape {
public Shape(String str) {
// Create object from string representation
}
public Shape clone() {
// Need new way to do this
return new Shape(this.toString());
}
public String toString() {
// Correctly overriden toString()
}
}

You can try to use reflection:
public abstract class AClonable implements Cloneable{
private String val;
public AClonable(){
}
public AClonable(String s){
val=s;
}
public String toString(){
return val;
}
#Override
public AClonable clone(){
try {
System.out.println(getClass().getCanonicalName());
AClonable b= getClass().getDeclaredConstructor(String.class).newInstance(val);
return b;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
in the clone() method you call getClass(). Because the ACloneble ist abstract, there call will allways go to the concrete class.
public class ClonebaleOne extends AClonable{
public ClonebaleOne(){
super();
}
public ClonebaleOne(String s) {
super(s);
// TODO Auto-generated constructor stub
}
}
and
public class ClonebaleTwo extends AClonable{
public ClonebaleTwo(){
super();
}
public ClonebaleTwo(String s) {
super(s);
// TODO Auto-generated constructor stub
}
}
and finally
public static void main(String[] args){
AClonable one = new ClonebaleOne("One");
AClonable tow= new ClonebaleTwo("Two");
AClonable clone = one.clone();
System.out.println(clone.toString());
clone = tow.clone();
System.out.println(clone.toString());
}
Output:
ClonebaleOne
One
ClonebaleTwo
Two
But it's more a hack than a solution
[EDIT] my two clones were faster than ;)
[EDIT] To be complete. Another implentation of clone() can be
#Override
public AClonable clone(){
try {
ByteArrayOutputStream outByte = new ByteArrayOutputStream();
ObjectOutputStream outObj = new ObjectOutputStream(outByte);
ByteArrayInputStream inByte;
ObjectInputStream inObject;
outObj.writeObject(this);
outObj.close();
byte[] buffer = outByte.toByteArray();
inByte = new ByteArrayInputStream(buffer);
inObject = new ObjectInputStream(inByte);
#SuppressWarnings("unchecked")
Object deepcopy = inObject.readObject();
inObject.close();
return (AClonable) deepcopy;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
when your abstract class implements Serialazable. There you write your object to disc and create a copy with the value from the disc.

You can't create deep clone of abstract class because they can't be instantiated. All you can do is shallow cloning by using Object.clone() or returning this
#Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
or
#Override
public Object clone() throws CloneNotSupportedException {
return this;
}
An abstract class can act as a reference, and it cannot have an instance so shallow cloning works in this case
OR
As a better approach, you can declare clone() as abstract and ask child class to define it, something like this
abstract class Shape {
private String str;
public Shape(String str) {
this.str = str;
}
public abstract Shape clone();
public String toString() {
return str;
}
}
class Circle extends Shape {
public Circle(String str) {
super(str);
}
#Override
public Shape clone() {
return new Circle("circle");
}
}

Although I doubt it is a good idea, you could use reflection:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test {
public static void main(String[] args) {
Square s1 = new Square("test");
Square s2 = (Square) s1.clone();
// show that s2 contains the same data
System.out.println(s2);
// show that s1 and s2 are really different objects
System.out.println(s1 == s2);
}
public static abstract class Shape {
private String str;
public Shape(String str) {
this.str = str;
}
public Shape clone() {
try {
Class<?> cl = this.getClass();
Constructor<?> cons = cl.getConstructor(String.class);
return (Shape) cons.newInstance(this.toString());
} catch (NoSuchMethodException | SecurityException |
InstantiationException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
#Override
public String toString() {
return str;
}
}
public static class Square extends Shape {
public Square(String str) {
super(str);
}
}
}

You can resolve with reflection:
public abstract class Shape {
private String str;
public Shape() {
}
protected Shape(String str) {
this.str = str;
}
public Shape clone() throws CloneNotSupportedException
{
try {
return (Shape)getClass().getDeclaredConstructor(String.class).newInstance(this.toString());
} catch (Exception e) {
throw new CloneNotSupportedException();
}
}
public String toString() {
return "shape";
}
public class Round extends Shape
{
public Round()
{
super();
}
protected Round(String str) {
super(str);
}
#Override
public String toString() {
return "round";
}
}
main(){
Shape round = new Round();
Shape clone = round.clone();
System.out.println(round);
System.out.println(clone);
}
but - IMO - is a poor implementation and error-prone with a lot of pits; the best use of Cloneable and Object.clone() is to not use them! You have a lot of way to do the same thing (like serialization for deep-clone) and shallow-clone that allow your a better control of flow.

Related

Generic Singleton in Java

Why does the following code throws java.lang.InstantiationException: generics.SingletonFoo$A?
public class SingletonFoo {
private static Object _tn;
public static <T> T instance(Class<T> t) {
if (_tn != null) {
return (T) _tn;
}
try {
_tn = t.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return (T) _tn;
}
private class A{
public A() {
}
}
public static void main(String[] args) {
System.out.println(SingletonFoo.instance(A.class));
}
}
Is it related to type erasure somehow and it's not possible to create generic singleton in Java?
Here A is not static class. Which means it contains a reference to the containing SingletonFoo (implicitly), which means you likely can't instantiate it via newInstance.
try to make it static or move it out of the class it if it doesn't need to be inner class.
Solution 1 : make A a static member class
private static class A{
public A() {
}
}
Soution 2:make it outside
public class SingletonFoo {
private static Object _tn;
public static <T> T instance(Class<T> t) {
if (_tn != null) {
return (T) _tn;
}
try {
_tn = t.newInstance();
;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return (T) _tn;
}
public static void main(String[] args) {
System.out.println(SingletonFoo.instance(A.class));
}
}
class A {
public A() {
}
}

call the same method name from instances different type

I have some libraries from external company, I want to use this API. I try to implement calling this API, my logic should call the same method name. I have duplicate codes, I want to avoid to do this. I'm beginner and subjects like interfaces, polymorphism are little bit difficult to me.
public void modPeople(Object person)
{
if (person instanceof com.company.persontype1)
{
com.company.persontype1 fireman = (com.company.persontype1) person;
String name = fireman.getName();
if (name!=null ) {
...
fireman.set_name();
fireman.save();
}
permissions = fireman.get_Permissions();
...
permissions = fixperm (permissions);
fireman.set_Permissions();
};
if (person instanceof com.company.persontype2)
{
com.company.persontype2 nurse = (com.company.persontype2) person;
String name = nurse.getName();
if (name!=null ) {
...
nurse.set_name();
nurse.save();
}
permissions = nurse.get_Permissions();
...
permissions = fixperm (permissions);
nurse.set_Permissions();
};
}
First of all I should mention that the methodology which you requested in your question is called "Duck Typing". Generally this technology is possible in Java (see below the example) but it's not widely used in Java. There could be performance hits etc. It would be much better to introduce a proper inheritance/interface level instead.
Also the provided example don't deal with exceptions properly etc. It's just a quick and quite dirty "demostration of the technology". Feel free to adapt it for your needs.
It's Java7 (for multi-catch clauses, you may refactor this with ease).
ISomeIterface.java (it contains all common methods implemented by classes which are used in your "bad code"):
package org.test;
public interface ISomeInterface {
public String getName();
public void setName(String _name);
public void save();
// specify other common methods
}
ReflectCaller.java:
package org.test1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import org.test.ISomeInterface;
public class ReflectCaller {
private final Method[] methods = ISomeInterface.class.getDeclaredMethods();
private final Map<Class<?>, Method[]> maps = new HashMap<Class<?>, Method[]>();
public void inspectClass(Class<?> _clazz) throws NoSuchMethodException, SecurityException {
final Method[] ms = new Method[methods.length];
int i = 0;
for(final Method m: methods) {
ms[i] = _clazz.getMethod(m.getName(), m.getParameterTypes());
i++;
}
maps.put(_clazz, ms);
}
public ISomeInterface wrapper(Object _obj) {
final Method[] ms = maps.get(_obj.getClass());
// To be replaced by guava's Preconditions.checkState()
if (ms == null)
throw new NoSuchElementException(String.format("Class %s is unregistered", _obj.getClass().getName()));
return new SomeInterfaceImpl(_obj, ms);
}
private static class SomeInterfaceImpl implements ISomeInterface {
private final Object obj;
private final Method[] ms;
public SomeInterfaceImpl(Object _obj, Method[] _ms) {
ms = _ms;
obj = _obj;
}
#Override
public String getName() {
try {
return (String) ms[0].invoke(obj);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
#Override
public void setName(String _name) {
try {
ms[1].invoke(obj, _name);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
#Override
public void save() {
try {
ms[2].invoke(obj);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
}
And test class ReflectTest.java. Notice that classes ReflectTest.Test and ReflectTest.Test2 has the same methods as ISomeInterface but don't implement it, they are completely independent from that interface and from each other.
package org.test2;
import org.test.ISomeInterface;
import org.test1.ReflectCaller;
public class ReflectTest {
private final ReflectCaller rc;
ReflectTest(Class ... _classes) throws NoSuchMethodException, SecurityException {
rc = new ReflectCaller();
for(final Class c: _classes)
rc.inspectClass(c);
}
void callSequence(Object _o) {
// this function demonstrates the sequence of method calls for an object which has "compliant" methods
ISomeInterface tw = rc.wrapper(_o);
tw.setName("boo");
System.out.printf("getName() = %s\n", tw.getName());
tw.save();
}
public static class Test {
public String getName() {
System.out.printf("%s.getName()\n", getClass().getName());
return "boo";
}
public void setName(String _name) {
System.out.printf("%s.setName(%s)\n", getClass().getName(), _name);
}
public void save() {
System.out.printf("%s.save()\n", getClass().getName());
}
}
public static class Test2 {
public String getName() {
System.out.printf("%s.getName()\n", getClass().getName());
return "boo2";
}
public void setName(String _name) {
System.out.printf("%s.setName(%s)\n", getClass().getName(), _name);
}
public void save() {
System.out.printf("%s.save()\n", getClass().getName());
}
}
public static void main(String[] args) {
ReflectTest rt;
try {
rt = new ReflectTest(Test.class, Test2.class);
} catch (NoSuchMethodException | SecurityException e) {
System.out.println(e);
System.exit(2);
return;
}
rt.callSequence(new Test());
rt.callSequence(new Test2());
}
}

organizing unittests in java/junit for testing classes with common api

I am implementing some elementary sorting algorithms (for the purpose of learning) ,and want to write unittests for them .All the sorting programs have the following common api
...
public static void sort(Comparable[] a);
...
public static boolean isSorted(Comparable[] a);
...
public static boolean isSorted(Comparable[] a),int from ,int to;
...
So,I wrote the following tests for testing the isSorted() method in SelectionSort
public class SelectionSortTests {
String[] a ;
#After
public void tearDown() throws Exception {
a = null;
}
#Test
public void arraySortedSingleElement(){
a = new String[]{"A"};
Assert.assertTrue(SelectionSort.isSorted(a));
}
#Test
public void arraySortedDistinctElements(){
a = new String[]{"A","B","C","D"};
Assert.assertTrue(SelectionSort.isSorted(a));
}
#Test
public void arrayNotSorted(){
a = new String[]{"A","B","C","B"};
Assert.assertFalse(SelectionSort.isSorted(a));
}
...
}
Now I feel that if I were to write tests for say InsertionSort,ShellSort etc ,they would look the same..Only the name of the class under test will change..
So,how should I organize the tests? Is a suite the answer or can I do better using reflection - may be write a driver program to which I can add a list of names of classes to be tested, and the driver invokes runs the common unit tests by passing the classname to it..
I realize this is a common situation..would like to know how this can be handled without spittle or cellotape
UPDATE:
thanks #BevinQ and #Matthew Farwell ,I tried to solve this using Parameterized unit tests.
Used reflection to call the static method ..
Seems to work :) though I think it can still be refactored to avoid duplicate code
#RunWith(Parameterized.class)
public class ParameterizedSortTests {
private Class classToTest;
private Method methodToTest;
public ParameterizedSortTests(String packageName,String classToTest) {
super();
try {
this.classToTest = Class.forName(packageName+"."+classToTest);
} catch (ClassNotFoundException e) {
System.out.println("failed to get class!!");
e.printStackTrace();
}
}
//method return collection of class names to be tested
#Parameterized.Parameters
public static List<Object[]> classesToTest(){
return Arrays.asList(new Object[][]{
{"elemsorts","SelectionSort"} ,
{"elemsorts","InsertionSort"}
});
}
public void setMethod(String method,Class...args){
try {
this.methodToTest = this.classToTest.getMethod(method, args);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
#Test
public void arrayIsSorted(){
setMethod("isSorted",Comparable[].class);
String[] a = new String[]{"A","B","C","D"};
Boolean arraySorted = null;
try {
arraySorted = (Boolean)this.methodToTest.invoke(null, new Object[]{a});
System.out.println(this.methodToTest+"returned :"+arraySorted);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Assert.assertTrue(arraySorted);
}
#Test
public void arrayIsNotSorted(){
setMethod("isSorted",Comparable[].class);
String[] a = new String[]{"A","B","C","B"};
Boolean arraySorted = null;
try {
arraySorted = (Boolean)this.methodToTest.invoke(null, new Object[]{a});
System.out.println(this.methodToTest+"returned :"+arraySorted);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//System.out.println("arraySorted="+arraySorted);
Assert.assertFalse(arraySorted);
}
}
for interface
public abstract class AbstractSortTests {
String[] a ;
#After
public void tearDown() throws Exception {
a = null;
}
protected abstract Sorter getSorter();
#Test
public void arraySortedSingleElement(){
a = new String[]{"A"};
Assert.assertTrue(getSorter().isSorted(a));
}
#Test
public void arraySortedDistinctElements(){
a = new String[]{"A","B","C","D"};
Assert.assertTrue(getSorter.isSorted(a));
}
...
}
public class SelectionSortTests extends AbstractSortTests {
protected Sorter getSorter(){
return SelectionSort.getInstance();
}
}
public class QuickSortTests extends AbstractSortTests {
protected Sorter getSorter(){
return QuickSort.getInstance();
}
}
using reflection it is a bit messier but still do-able. I have not tested this code so might have
a couple of bugs, but have used this method in the past. Using interfaces would be the preferred method in 99% of cases.
public abstract class AbstractSortTests {
String[] a ;
#After
public void tearDown() throws Exception {
a = null;
}
protected abstract Sorter getSorter();
#Test
public void arraySortedSingleElement() throws Exception{
a = new String[]{"A"};
Assert.assertTrue(executeMethod(getSorterClass(), "isSorted", a);
}
#Test
public void arraySortedDistinctElements() throws Exception{
a = new String[]{"A","B","C","D"};
Assert.assertTrue(executeMethod(getSorterClass(), "isSorted", a);
}
private void executeMethod(Class<?> sortClass, String methodName, String[] values) throws Exception{
return sortClass.getDeclaredMethod(methodName, new Class[]{String[].class}).invoke(null, new Object[]{values});
}
...
}
public class SelectionSortTests extends AbstractSortTests {
protected Class<?> getSorterClass(){
return SelectionSort.class;
}
}
As #BevynQ says, you'll make life a lot easier for yourself if you make your methods non-static, and you implement an interface (called Sorter below). The you can easily use Parameterized. This is a very quick example of how to use it, (untested, uncompiled)
#RunWith(Parameterized.class)
public class SorterTest {
#Parameters
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {
{ new SelectionSort() },
{ new BubbleSort() }
});
}
private final Sorter sorter
public SorterTest(Sorter sorter) {
this.sorter = sorter;
}
#Test
public void arraySortedSingleElement(){
String[] a = new String[]{"A"};
Assert.assertTrue(sorter.isSorted(a));
}
#Test
public void arraySortedDistinctElements(){
String[] a = new String[]{"A","B","C","D"};
Assert.assertTrue(sorter.isSorted(a));
}
#Test
public void arrayNotSorted(){
String[] a = new String[]{"A","B","C","B"};
Assert.assertFalse(sorter.isSorted(a));
}
}
why not something like this?
#Test
public void arraySortedDistinctElements(){
a = new String[]{"A","B","C","D"};
Assert.assertTrue(SelectionSort.isSorted(a));
Assert.assertTrue(InsertionSort.isSorted(a));
Assert.assertTrue(QuickSort.isSorted(a));
}
I don't think you have more than 10 different sortings to test. so it should be good.
otherway, you can declare all Sorting classes in Array and load using Class properties.

Create an exception-safe wrapper of a class

I have a legacy class C1, implementing interface I, that may throw some exceptions.
I want to create a class C2, also implementing interface I, that is based on an instance of C1, but catches all exceptions and does something useful about them.
Currently my implementation looks like this:
class C2 implements I {
C1 base;
#Override void func1() {
try {
base.func1();
} catch (Exception e) {
doSomething(e);
}
}
#Override void func2() {
try {
base.func2();
} catch (Exception e) {
doSomething(e);
}
}
...
}
(Note: I could also make C2 extend C1. This does not matter for the current question).
The interface contains many functions, so I have to write the same try... catch block again and again.
Is there a way to reduce the amount of code duplication here?
You can make a Proxy, it could actually be generic
interface I1 {
void test();
}
class C1 implements I1 {
public void test() {
System.out.println("test");
throw new RuntimeException();
}
}
class ExceptionHandler implements InvocationHandler {
Object obj;
ExceptionHandler(Object obj) {
this.obj = obj;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(obj, args);
} catch (Exception e) {
// need a workaround for primitive return types
return null;
}
}
static <T> T proxyFor(Object obj, Class<T> i) {
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), new Class[] { i },
new ExceptionHandler(obj));
}
}
public class Test2 {
public static void main(String[] args) throws Exception {
I1 i1 = ExceptionHandler.proxyFor(new C1(), I1.class);
i1.test();
}
}

java generic cast question

I want to implement a sort of transfer object pattern. So, i have a method that fills object´s properties via BeanUtils.copyProperties(..,..) (apache common).
Here is the code:
public abstract class BaseTO<TObject> {
public Long id;
/***
* Obtains id of the object that´s transfered
* #return object´s id
*/
public Long getId() {
return id;
}
/****
* set transfered object´s id
* #param id object´s id
*/
public void setId(Long id) {
this.id = id;
}
/***
* Fill transfer object properties.
* #param entity entity to be transfered
* #return self reference
*/
public BaseTO<TObject> build(TObject entity){
try {
BeanUtils.copyProperties(this, entity);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
customDataTransformation(entity);
return this;
}
protected void customDataTransformation(TObject entity) {
}
}
CustomerTO Class
public class CustomerTO extends BaseTO<Customer> {
private String name;
private String surname;
private String email;
private String sex;
private DocumentType documentType;
private String documentNumber;
--- getters and setters
#Override
protected void customDataTransformation(Customer entity) {
this.sex = Sex.MALE.equals(entity.getSex()) ? "M" : "F";
}
}
the problem
CustomerTO toEdit = (CustomerTO) (customerId!=null ? new CustomerTO().build(entityObject):new CustomerTO());
as you can see here have to cast to (CustomerTO). I want if it´s possible avoid that, to make the code simpler.
Is it posible that public BaseTO build(TObject entity) can return the object of the subclass??
I hope to be clear.
Thanks in advance.
Maybe try this:
class BaseTO<TObject, R extends BaseTO<TObject,R>> {
public R build(TObject entity) {
and then CustomerTO:
class CustomerTO extends BaseTO<Customer, CustomerTO> {
or less restrictively, only change the build signature:
public <X extends BaseTO<TObject>> X build(TObject entity) {
But IMHO better approach will be simply adding constructor to TO with TObject parameter.
public BaseTO(TObject entity) {
try {
BeanUtils.copyProperties(this, entity);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
customDataTransformation(entity);
}
then in each extending class create simple constructor
public CustomerTO(Customer entity) {
super(entity);
}
and forget about the build method and use it simply
CustomerTO toEdit = (customerId!=null ? new CustomerTO(entityObject):new CustomerTO());
This compiles:
public class BaseTO<T> {
public BaseTO<T> build(T entity) {
return this;
}
public static class CustomerTO extends BaseTO<String> {
#Override public CustomerTO build(String string) {
return (CustomerTO) super.build(string);
}
}
but you will have to override build for all subclasses of BaseTO. You write explicitly the cast only once instead of every time you call build.
EDIT: see the point raised by #Paul in the comments above. You might be suffering from "give a man a hammer and everything looks like a nail to him."

Categories