Cloning objects of inner classes - java

I have written a class A such as following
class A <E> { // class A has objects of E
int x;
private B<T> next // a object of inner class
class B<T> {
// an inner class having objects of type T
T[] elements = (T[]) Object[x];
// has other stuff including many objects
}
public A<E> func ( B<E> val ){
Here I want to clone the value of val so that I can do different operations on other
}
The problem comes that I wish to write B<E> Temp = B<E>Value.clone() where Value is defined in the code.
but it says that clone is not visible.
What should I do to make it so....
Thanks a lot...

clone() is protected so you just need to redefine in B to do whatever you need.

Here an example to the answers from Peter (not tested, may need some syntax checks):
class A <E> { // class A has objects of E
int x;
private B<T> next // a object of inner class
class B<T> implements Cloneable {
public B<T> clone() {
try {
B<T> klon = (B<T>) super.clone();
// TODO: maybe clone the array too?
return klon;
}
catch(CloneNotSupportedException) {
// should not occur
throw new Error("programmer is stupid");
}
}
// an inner class having objects of type T
T[] elements = (T[]) Object[x];
// has other stuff including many objects
}
public A<E> func ( B<E> val ){
B<E> clone = val.clone();
// more code
}

It's better to not use clone() but to implement a copy constructor on B:
class B extends A {
// an inner class having objects of type
List<String> strings = ArrayList<String>();
public B(B that) {
super(that); // call the superclass's copy constructor
this.strings = new ArrayList<String>();
this.strings.add(that.strings);
}
// ...
}
then call
public C func ( B val ){
B clone = new B(val);
}
(removed the generics stuff to limit demonstration on the copy constructor itself)

Related

Interface methods in a class that does not implement it?

public interface Iterator<T> {
// Returns true if the iterator is valid (points to an element), false otherwise.
boolean isValid();
// Returns the current element and moves forward. This method can only be called if the iterator is valid. If the iterator points to the last element, it becomes invalid after the call.
T next();
// Returns the current element and moves backwards. This method can only be called if the iterator is valid. If the iterator points to the first element, it becomes invalid after the call.
T prev();
}
In a class that does not implement interface Iterator, how is it possible to create a method that returns Iterator<K>, when you can only create methods for an interface inside a class that implements it?
public class ABC<K> implements EFG<K>{
public Iterator<K> minIt() {
//method body
//return Iterator<K> variable
}
}
The class ABC containing the method minIt() does not implement Iterator<T>
(No classes implement the interface Iterator <T> )
You can use an Anonymous Class that implements the interface:
For instance:
interface Foo<T> {
T foo();
}
class Bar<T> {
T t;
public Foo<T> bar() {
return new Foo<T>() { // <-- Anonymous class implementing `Foo`
public T foo() {
return t;
}
};
}
}
Execution:
Bar<String> b = new Bar<>();
b.t = "hello"; // with a setter in real life
Foo<String> f = b.bar();
f.foo(); // will return "hello"
The other option which I think would be the most common is to use a method that returns the interface, for instance the list interface has an iterator() method even though it itself doesn't implements the Iterator interface.
List<String> list = new ArrayList<>();
Iterator<String> stringIterator = list.iterator();
Here's the implementation
Simple. By making a class that implements it. Note that you have a type that you came up with on your own and you named it Iterator. Given that java.util.Iterator exists, this is a really bad idea. You should pick another name.
public class ABC<K> implements EFG<K> {
// Let's say this contains the items that can be iterated over.
private List<K> list = new ArrayList<K>();
class MyIterator implements my.pkg.Iterator<K> {
private int position = 0;
#Override public boolean isValid() {
return position > -1 && position < list.size();
}
#Override public K next() {
if (!isValid()) throw new NoSuchElementException();
return list.get(position++);
}
#Override public K prev() {
if (!isValid()) throw new NoSuchElementException();
return list.get(position--);
}
}
public Iterator<K> minIt() {
return new MyIterator<K>();
}
}
Note that classes that you put in classes can only be constructed in instance contexts within that class: They have a 'secret' field of your outer's type. Hence why the code in MyIterator can access the list field of your outer class.
Java has 'anonymous inner class literal' syntax which lets you shorten this: Instead of explicitly declaring class MyIterator, you can also write:
public Iterator<K> minIt() {
return new your.pkg.Iterator<K>() {
private int position = 0;
#Override public boolean isValid() {
// same code goes here as the previous snippet
}
};
}
This anonymous inner class form is a lot more common. It's just syntax sugar - a shorter way to write the same thing.

passing Object Instances as generics to a method

I have a scenario similar to the below example.
I have two different objects and have already created instances from them. I need to pass these instances as generic to a method parameters.
I tried passing the method parameters as Class obj but it didnt work
Class A
{
A()
{
List<String>collection = new ArrayList<>();
}
}
Class B
{
B()
{
List<String>collection = new ArrayList<>();
}
}
Class Main()
{
A a = new A();
B b = new B();
methodTest(a);
methodTest(b);
void methodTest(Class<T> genericObj)
{
genericObj.collection.add("1");
// I need to pass both the instance A and instance B to
genericObj
}
}
Need some suggestions.
You don't pass generics to methods, since generic is a Type, not an object.
What you do is, you pass an object; with generic being declared in your class.
E.g.
public class Test <T extends ClasThatHasCollection> {
void methodTest(T genericObj) {
genericObj.collection.add("1");
}
}
However in your case, generics seem like an overkill!
Just have a parent class P that has .collection instance variable; and have both classes A and B extend P; and pass object type P into methodTest:
public class P {
public Collection collection;
// ....
}
public class A extends P {
}
void methodTest(P genericObj) {
P.collection.add("1");
}
The simplest way would be to create a base class and have A and B inherit from it.
In the method you use the base class as the type.
This is valid since both A and B extend it.
For example:
class Base {
List<String> collection;
Base() {
collection = new ArrayList<>();
}
}
class A extends Base{
A(){
super()
}
}
class B extend Base{
B(){
super()
}
}
void methodTest(Base genericObj)
{
genericObj.collection.add("1");
}
Another possibility is to use an interface. This would be useful if the collections are not the same type and are therefore not defined in the base object.
Using an interface:
interface MyInterface{
public ArrayList<> getCollection();
}
class A implements MyInterface {
List<String> collection;
A(){
collection = new ArrayList<>();
}
public ArrayList<> getCollection(){
return collection;
}
}
class B implements MyInterface{
List<String> collection;
B(){
collection = new ArrayList<>();
}
public ArrayList<> getCollection(){
return collection;
}
}
void methodTest(MyInterface genericObj)
{
genericObj.getCollection().add("1");
}

Return data type the same as class name via superclass?

I have an abstract class which has one abstract method. I want this method to return the same data type as the class which is overriding the method without having to cast the result of create or having to make a new method declaration on each subclass. I want it to all be declared seemlessly from the parent class.
I want the method to return a object whose data type is the same as the class it was called on.
EDIT: I removed print as people are getting confused with what I am asking
abstract class A
{
public abstract ... create();
}
class B extends A
{
#override
public ... create()
{
return new B...;
}
}
class C extends A
{
#override
public ... create()
{
return new C...;
}
}
Such that
B x1 = new B();
B x2 = x1.create();
// Since create was called on a B object
// a B object is returned, NOT AN "A" object
C y1 = new C();
C y2 = y1.create();
// create makes a C object this time,
// because it's called on a C object
// Problem: create() returns A object, even when
// called from class B or C.
// I want create() to return a B object if called from a B object.
What would be a good way of going about this? Thanks.
I no longer think this is the right answer. It's an answer, but is over-complicated. See my other answer.
There is no notion of a "self" type in Java's generics. The best you can do is to use self-bounded generics:
abstract class A<T extends A<T>>
{
public abstract T create();
}
Then, in your subclasses:
class B extends A<B>
{
#override
public B create()
{
return new B...;
}
}
Actually, there is an easier way to do it than with my other answer: just use a covariant return type in the subclass:
abstract class A {
public abstract A create();
}
class B extends A {
#Override public B create() {
return new B...
}
}
This is more pleasant if you are dealing with instances of A, since you don't have to make it generic (or, shudder, raw).
It also gives just as much of a guarantee that it returns a "self" type, i.e. no guarantee at all.
this.getClass() to get the class object, or, this.getClass().getSimpleName() to get a string of class name.
I have to question the design approach.
I'd be going for
abstract class A {
abstract Supplier<? extends A> create();
}
with
class B extends A {
public Supplier<B> create() {
return B::new;
}
}
(and C accordingly).
Then, there is
A b = new B();
A anotherB = b.create().get(); // will create a B
A c = new C();
A anotherC = c.create().get(); // will create a C
You don't need to make your create method abstract. If all the subclasses have a no-argument constructor, then you can just write this (in class A)
public A create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}
This checks the class of the object that you called the method on; and creates a new object of the same class, using its no-argument constructor.
Update
OP's comment suggests that they don't want to have to cast the returned value. If this is a requirement, then the casting can be avoided by changing the method signature as follows.
public <T extends A> T create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}

How to parse a generic type through several levels of extends?

I have the following 3 classes:
public class MyClass1<T extends MyClass1> {
private List list = new ArrayList();
public T add(Object... o) {
Collections.addAll(this.list, o);
return (T) this;
}
public MyClass2 two() {
MyClass2 n = new MyClass2();
add(n);
return n;
}
}
public class MyClass2<T extends MyClass2> extends MyClass1<MyClass2> {
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
public class MyClass3<T extends MyClass3> extends MyClass2<MyClass3> {
}
I want to call the methods in a chain. Like this:
MyClass1 m1 = new MyClass1();
m1.add(1).add(2).two().add(3).three().add(4);
For some reason add(3) returns MyClass1, where I would have expected it to return MyClass2. If I remove <T extends MyClass2> from MyClass2, add(3) returns MyClass2 as desired, but then MyClass3 cannot extend MyClass2 with a type.
How can I make this work, so I can chain all my methods and still use the add(Object...) method from all my classes?
UPDATE:
The above is clearly an example. What I'm really trying to create here is a simple tool for building MySQL queries. I have a lot of EJB3 entities that already define my table and column names, but need to make a few native queries, because some things just cannot be achieved with EJB-QL. Yet, I don't want to have to specify table and column names more than once in my code, and therefore need a tool that can create a native MySQL query using EJB3 entities. When I use the code I've created, it might look like this:
new Query().select().field(MyEntity_.id).field(MyEntity_.name).field(MyOtherEnt_.type);
Or:
new Query().join().left(MyOtherEnt_.myEntityId);
Here I might have a Query object, which specifies some generic MySQL syntax and then extend it. It could be something like this: Query > extended by Select > extended by SubQuery. The whole thing is customized to the specific project I'm working on.
add(3) returns MyClass1 because method add is member of class MyClass1. You would have to override add method in your extending classes in order to return different datatype.
The definition of MyClass2 should be more or less like that
class MyClass2<T extends MyClass2> extends MyClass1<MyClass2> {
#Override
public T add(Object... o) {
super.add(o);
return (T)this;
}
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
anyway, I dont know what are you trying to achieve, but IMHO you have took bad approach. Moreover you are not declaring types T when you are creating new parametrized objects, so all in all, for compiler and JRE everything here is just of Object type.
Your biggest problem is that your're extending raw types. Change:
public class MyClass1<T extends MyClass1> {
to
public class MyClass1<T extends MyClass1<T>> {
Once you use a raw type, all generic info is stripped from the class.
Similar for the other classes.
For now I've decided to make it a little more simple and have MyClass3 extend MyClass1 instead of MyClass2. If I keep it at "2 levels", it works, so I'll just have to live with the constrain that MyClass3 cannot extend MyClass2, if I want to be able to chain the methods from MyClass1. My code then looks like this:
public class MyClass1<T extends MyClass1> {
private List list = new ArrayList();
public T add(Object... o) {
Collections.addAll(this.list, o);
return (T) this;
}
public MyClass2 two() {
MyClass2 n = new MyClass2();
add(n);
return n;
}
}
public class MyClass2 extends MyClass1<MyClass2> {
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
public class MyClass3 extends MyClass1<MyClass3> {
public void four() {}
}
And I can write:
MyClass1 m1 = new MyClass1();
m1.add(1).add(2).two().add(3).add(4).three().add(5).add(6).four();

How to sort two different objects in a collection?

Suppose I have two classes CLassA and CLassB. And they have one atributte in common, for example the number of elements that each class holds.
How can i create a collection from objects of ClassA and CLassB and sort by that attribute (ascending of descending order, doesn't matter)?
I made a collection of type but when I try to implement the Comparable Interface i can't acess to that method (a get that returns the nr of elements for example).
What solutions do I have?
Thanks for your help!
You could make a custom java.util.Comparator and sort using the Collections.sort(List list,
Comparator c) method.
Really ClassA and ClassB should be related either through an inheritance hierarchy, or by a common interface if you are going to put them both in the same collection.
The simplest thing would be to have a common interface that provides an accessor method for the common attribute. And then the comparator could use that method (through the interface) for fetching the value from ClassA's instance as well as ClassB's instance.
Hmm.. is it possible for ClassA and ClassB to share an interface?
interface InterfaceZ
{
int getCount();
}
class ClassA implements InterfaceZ
{
int getCount() { return _myArray.length; }
}
class ClassB implements InterfaceZ
{
int getCount() { return _complexCollection.size(); }
}
Then just sort the list like so:
List<InterfaceZ> myArray;
... fill up array ...
Collections.sort(myArray, new Comparator<InterfaceZ>() {
public int compare(InterfaceZ o1, InterfaceZ o2) {
return o2.getCount() - o1.getCount();
}});
If you have access to the declaration of CLassA and ~B, then go with a common interface, if not you could write a Wrapper for both Classes:
I defined - against the description - my own classes ~A and ~B, to have something to test. Imagine they're foreign source, and you just have access to the classes.
import java.util.*;
public class SortAB
{
class CLassA {
int [] elements;
public CLassA (int [] a) {elements = a;}
public int getElementCount () {return elements.length;}
}
class CLassB {
List <Integer> elements;
public CLassB (List <Integer> l) {elements = l;}
public int getElementCount () {return elements.size ();}
}
/** a common element-count-wrapper with compareTo method */
abstract class EcWrapper <T> implements Comparable <EcWrapper> {
public abstract int getElementCount ();
public int compareTo (EcWrapper o) {return getElementCount () - o.getElementCount ();}
}
/** concrete Wrapper for CLassA */
class EcAWrapper extends EcWrapper <CLassA> {
private CLassA inner;
public EcAWrapper (CLassA t) {
inner = t;
}
public int getElementCount () {return inner.getElementCount (); }
}
/** concrete Wrapper for CLassB */
class EcBWrapper extends EcWrapper <CLassB> {
private CLassB inner;
public EcBWrapper (CLassB t) {
inner = t;
}
public int getElementCount () {return inner.getElementCount (); }
}
// testing
public SortAB ()
{
int [] ia = {3, 5, 7, 6, 9, 11, 14};
List <Integer> il = new ArrayList <Integer> ();
for (int i: ia)
il.add (i);
il.add (15);
il.add (16);
CLassA a = new CLassA (ia);
CLassB b = new CLassB (il);
List <EcWrapper> list = new ArrayList <EcWrapper> ();
list.add (new EcBWrapper (b));
list.add (new EcAWrapper (a));
show (list);
Collections.sort (list);
show (list);
}
public static void main (String args[])
{
new SortAB ();
}
public static void show (List <EcWrapper> list)
{
for (EcWrapper e: list)
System.out.println ("\t" + e.getElementCount ());
System.out.println ("---");
}
}

Categories