One way to duplicate non-identical objects is to implement the Cloneable interface and override ʻObject # clone`.
However, when I wanted to duplicate an object using a generic type like the following code, I was frustrated because I could not access ʻObject # clone` directly, so I can duplicate an object even if I use a generic type. I decided to devise various things like [^ best].
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> T cloneSample(T obj) {
return (T) obj.clone(); //Compile error (invisible clone method)
}
}
python
public interface CloneablePublicly<T> {
T clone();
}
ʻI made an interface to call a method to clone from the outside instead of Object # clone`. Let's implement this for the class of the object that uses the generic type.
Implementation example
class Sample implements Cloneable, CloneablePublicly<Sample> {
int value;
public Sample(int value) {
this.value = value;
}
@Override public Sample clone() {
try {
return (Sample) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
}
Of course, the Cloneable interface is also implemented at the same time. If this is not implemented, it will throw a CloneNotSupportedException
.
After that, if you modify the method as follows, you can duplicate the object using the generic type.
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> T cloneSample(T obj) {
if (obj instanceof Cloneable && obj instanceof CloneablePublicly) {
return ((CloneablePublicly<T>) obj).clone();
}
return null;
}
}
Example of use
Sample samp1 = new Sample(1);
Sample samp2 = GenericsSample.cloneSample(samp1);
System.out.println(samp1.value); // 1
System.out.println(samp2.value); // 1
System.out.println(samp1 == samp2); //false (duplicate non-identical object)
If you don't want to return null, return the optional [^ cost] as follows: This also allows you to do nothing if you cannot duplicate the object.
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> Optional<T> cloneSample(T obj) {
return Optional.ofNullable(obj)
.filter(Cloneable.class::isInstance)
.filter(CloneablePublicly.class::isInstance)
.map(o -> ((CloneablePublicly<T>) obj).clone());
}
}
Example of use
Sample samp1 = new Sample(1);
GenericsSample.cloneSample(samp1).ifPresent(samp2 -> {
System.out.println(samp1.value); // 1
System.out.println(samp2.value); // 1
System.out.println(samp1 == samp2); //false (duplicate non-identical object)
});
// Sample samp1 = null;At that time, do nothing.
From @ saka1029's comment, we introduced interface inheritance and implementation using boundary type parameters. Thank you!
Inheritance of Cloneable interface
interface CloneablePublicly<T> extends Cloneable {
T clone();
}
This way you don't have to implement the Cloneable interface for the class of objects that use generic types. ~~ I completely forgot the inheritance function of the interface. ~~
Implementation example
class Sample implements CloneablePublicly<Sample> {
... //the same
}
python
class GenericsSample {
static <T extends CloneablePublicly<T>> T cloneSample(T obj) {
return Objects.isNull(obj) ? null : obj.clone();
}
}
Type safety is ensured using borderline parameters, eliminating the need for hand-cast cast inspection. The optional line has been completed.
python
class GenericsSample {
static <T extends CloneablePublicly<T>> Optional<T> cloneSample(T obj) {
return Optional.ofNullable(obj).map(CloneablePublicly::clone);
}
}
[^ best]: I searched a lot, but I couldn't find any material that looked good, so I made it myself. If you have any suggestions or suggestions on best practices, we apologize for the inconvenience, but we would appreciate it if you could teach us. [^ Cost]: According to "Effective Java 3rd Edition", it is costly to use Optional frequently, so it may be better to refrain from it if you are concerned about performance.
Recommended Posts