Beginner object references question - java

If I instantiate an object in a main class, say:
SomeObject aRef = new SomeObject();
Then I instantiate another object from the main class, say:
AnotherObject xRef = new AnotherObject();
How can the instance of AnotherObject make use of the aRef reference to access the methods in SomeObject? (To use the same instance of SomeObject)

Why not instantiate AnotherObject with a reference to the original SomeObject ?
e.g.
SomeObject obj = new SomeObject();
AnotherObject obj2 = new AnotherObject(obj);
and AnotherObject would look like:
// final used to avoid misreferencing variables and enforcing immutability
private final SomeObject obj;
public AnotherObject(final SomeObject obj) {
this.obj = obj;
}
so AnotherObject has a reference to the previously created SomeObject. It can then use this reference to call methods on. If the original object is not required outside the scope of AnotherObject, then create it inside AnotherObject and enforce encapsulation that way.

I think what you are asking is a question about scope. You're asking how can xRef use aRef during execution? The answer is that the aRef reference needs to be passed into the xRef object when it's being instantiated
xRef = new AnotherObject(aRef)
or after the instantiation you could have
xRef.setSomeObject(aRef)

The answer to his question is making the first class a static class.

xRef.SetSomeObject(aRef);
where SetSomeObject has a signature like
public void SetSomeObject(SomeObject obj)
{
obj.DoStuff();
}
and is a member function of the type AnotherObject.

The strategy design pattern and Decorator design pattern are 2 different ways you can do this.
For instance you can have:
class AnotherObject
{
private SomeObject mySomeObject;
public AnotherObject(SomeObject mySomeObject)
{
this.mySomeObject = mySomeObject;
}
function doSomethingUsingStrategy()
{
mySomeObject.doItTheMySomeObjectWay();
}
function setMySomeObject(SomeObject mySomeObject)
{
this.mySomeObject = mySomeObject;
}
}
Then later on, you can use a different strategy:
myAnotherObject.setMySomeObject(new ExtendsSomeObject);
myAnotherObject.doSomethingUsingStrategy()

You need to provide the reference to aRef to instances of AnotherObject either in the constructor: AnotherObject xRef = new AnotherObject(aRef) or using setter methods: xRex.setSomeObject(aRef). In this case AnotherObject needs to have an instance variable to store aRef that can be used internally like:
class AnotherObject {
SomeObject aRef;
public AnotherObject(SomeObject aRef) {
this.aRef = aRef;
}
public void doSomethingWithSomeObject() {
aRef.doSomething();
}
}
You could also pass instances of SomeObject to methods on AnotherObject that require them like xRef.doSomethingWithSomeObject(aRef).
class AnotherObject {
public void doSomethingWithSomeObject(SomeObject aRef) {
aRef.doSomething();
}
}

There are a bunch of ways to do it (as pointed out by others). You really want to think about your object structure though...
Perhaps your main method shouldn't even be instantiating aRef, perhaps it should be instantiated inside xRef's constructor (this is the case where xRef tends to be a "part" of the functionality of aRef.
If aRef can have multiple instances at some point you may not want to store it off at all, you may want to pass it in whenever an xRef method uses it.
This is where you need to consider your object model at a business logic level. What are the relationships between the objects, etc.
(My guess is that you want xRef to instantiate aRef and keep the reference itself, then if your "main" really needed to talk with aRef it could either ask xRef to forward the message or ask xRef for it's instance of aRef.)

You have to pass the ref and then do something with it.
class AnotherObject {
SomeObject someObject;
public void setSomeObject( SomeObject some ) {
this.someObject = some;
}
public void doSomethingWithSomeObject() {
this.someObject.someMethod();
}
..... rest of your code
}
That way you can use it like this in the main method
public static void main( String [] args ) {
SomeObject xRef = new SomeObject();
AnotherObject aRef = new AnotherObject();
// pass the ref...
aRef.setSomeObject( xRef );
// use it
aRef.doSomethingWithSomeObject();
}
Is that what you need?

Could AnotherObject have a member or property that has a type of SomeObject? That would be another way to handle this too.
So, if there was a "SomeObjectMember" member of the AnotherObject class:
xRef.SomeObjectMember = aRef;

Related

How to clone collection of unknown type?

Suppose I have collection, stored in
Collection<V> member;
or in
C member;
How to clone this class with also cloning this member?
How to clone this class with also cloning this member?
I assume you're overriding the clone method. So you could use the provided runtimeType of member to get a new instance:
public class MyObject<V, C extends Collection<V>> {
private C member = ...;
#Override
public MyObject clone(){
MyObject clone = new MyObject();
if(member != null){
try {
clone.member = member.getClass().newInstance();
clone.member.addAll(member);
} catch(InstantiationException | IllegalAccessException ignore){}
}
// clone other properties
return clone;
}
}
But this is quite dirty because you can never ensure that C has a default constructor or as mentioned by #shmosel, the collection could even be imutable. E.g. the addAll() call fails.
To overcome the above dirty way you could require a Supplier<C> when creating an instance of MyObject that way you could create your own collections as you wish:
private final Supplier<C> factory;
public MyObject(Supplier<C> factory){
this.factory;
}
And only create the member when it is first time used. By invoking factory.get().
That way you safely create the member variable when cloning the object. But then there's still the case with the imutability which is probably the breaker of any approach to copy the values from the member to clone.member.

Java: Is setters should make `Clone` or it's up to caller pass `new` copy?

What considered to be the best & common practice if I want to make sure that after setter is called the object cannot be modified from outside? In the code there is detailed simple self explained example, With 2 options dilemma.
//caller scope
CustomObject original = new CustomObject(params...); //original state 1
MyClass mMyClass = new MyClass(original);
original.modifyMe(params...); //original state 2
mMyClass.setCustomObject(original);
original.modifyMe(params...); //original state 3
/*!!!REQUIREMENT: mMyClass.CustomObject should be in state 2!!!*/
class MyClass {
private CustomObject mObject;
public MyClass() {
this.mObject = new CustomObject();
}
public MyClass(CustomObject obj) {
this.mObject = obj.Clone();
}
//mObject is private, modified only through setter
public getCustomObject() {
return this.mObject;
}
public setCustomObject(CustomObject obj) {
//Option 1 in the caller
//mMyClass.setCustomObject(new CustomObject(params...));
this.mObject = obj;
//Option 2 in the caller
//mMyClass.setCustomObject(callerCustomObject);
this.mObject = obj.Clone();
}
}
I wouldn't use clone here. Rather than making inefficient defensive copies, try making CustomObject immutable. You can modify state by adding withXXX methods (roughly equivalent to setXXXX) but they create a new instance of the host object (rather than the Object being passed in). Project lombok comes with some handy preprocessor annotations for creating Immutable objects with Withers. Also see the Immutables 2.0 project.
#AllArgsConstructor
class CustomObject {
#Wither #Getter
private final int state;
}
CustomObject one = new CustomObject(1);
CustomObject two = one.withState(2);
assertThat(one.getState(),equalTo(1));
assertThat(two.getState(),equalTo(2));
By using genuine Immutable Objects you will incur much less memory (& GC) and CPU overhead than with defensive copies - as well as much simpler code.

Accessing current object's sibling method

I have two (sibling) classes, both is subclass of the same parent. Parent contains all the methods that is shared by the two sibling, and the sibling classes contain only methods that are not shared and has different implementations.
Example,
class Parent() {
}
class Sibling1 extends Parent() {
byte[] sharedSecret;
int sharedSecretLength;
public generateKey() {
sharedSecret = keyAgree.generateSecret());
sharedSecretLength = sharedSecret.length);
}
}
class Sibling2 extends Parent() {
byte[] sharedSecret2;
int sharedSecretLength2;
public generateKey() {
sharedSecret2 = new byte[sharedSecretLength];
sharedSecretLength2 = keyAgree.generateSecret(sharedSecret2, 0);
}
public int getSharedSecretLength() {
return sharedSecretLength();
}
}
As you can see, both contains same method but implemented differently. My question is, if objects of both class (sibling1 and sibling2) are created AND obj2 generateKey to be generated successfully depends on sharedSecretLength of obj1. Example,
Parent obj1 = new Sibling1();
Parent obj2 = new Sibling2();
obj1 is instantiated in different class (Server class that I created) and obj2 in different class (Client that I created). If obj1 invoke it's own generateKey --> ((Sibling1)obj1).generateKey(), how can I use use getSharedSecretLength on the same object (obj1) to relay the needed information over to obj2's generateKey to generate successfully? I tried something like (in obj2's generateKey() ):
sharedSecret2 = new byte[Sibling1.sharedSecretLength];
...and it didn't work. Creating Sibling1 obj1 inside of Sibling2 class and then call it that way, for example,
Sibling1 xx = null;
.
.
sharedSecret2 = new byte[((Sibling1)xx).sharedSecretLength];
doesn't work because xx is new object. I am trying to use the old obj in which it generated it's key and contains sharedSecretLength that is not 0
If both obj1 and obj2 were created in the same class, it would have been easier.
Please help point me to the right direction
Instead of
((Sibling1)xx).sharedSecretLength
call it like
((Sibling1)xx).getSharedSecretLength()
In java, you have pass the empty parenthesis if it doesn't accept parameter and it doesnt work by field name, you will have to give the same method name as to what you have defined.
It sounds like you should refactor like this so that the generateKey method on Sibling2 has the argument it requires:
Sibling1 obj1 = new Sibling1();
obj1.generateKey();
Siblibg2 obj2 = new Sibling2();
obj2.generateKey(obj1.getSharedSecretLength());

How to clone object in java

This question already has answers here:
Java: recommended solution for deep cloning/copying an instance
(10 answers)
Closed yesterday.
I want to create a list/array of object with the same parent class which then I will use it for reference. but i dont know how to clone those object to make a new object.
here is the example
BigFoo a;
SmallFoo b;
ChickenFoo c;
List<Foo> foos;
foos.add(a);
foos.add(b);
foos.add(c);
Foo foo = foos.get(1).clone();
but in Java i found no clone function in the default function. I wonder how this is accomplished?
The general suggestion: use a copy constructor. In fact, only a class itself knows how to create a clone of itself. No class can clone an instance of another class. The idea goes like this:
public class Foo {
public List<Bar> bars = new ArrayList<Bar>();
private String secret;
// Copy constructor
public Foo(Foo that) {
// new List
this.bars = new ArrayList<Bar>();
// add a clone of each bar (as an example, if you need "deep cloning")
for (Bar bar:that.bars) {
this.bars.add(new Bar(bar));
}
// clone the secret value
this.secret = new String(that.secret);
}
// ...
}
So if we want to clone a foo, we simply create a new one based on foo:
Foo clonedFoo = new Foo(foo);
That's the recommended way to clone an instance.
copy constructor works well with inheritance. Consider a subclass
public ChildFoo extends Foo {
private int key;
public ChildFoo(ChildFoo that) {
super(that);
this.key = that.key;
}
}
Foo has a copy constructor and ChildFoo simply calls it from it's own copy constructor.
Your example is possible but not advisable. What will happen:
Foo a = new Foo();
ChildFoo b = new ChildFoo(a);
This would require a constructor on ChildFoo like:
public ChildFoo(Foo that) {
// call the copy constructor of Foo -> no problem
super(that);
// but how to initialize this.key? A Foo instance has no key value!
// Maybe use a default value?
this.key = 0;
}
Technically not a challenge but b is not a clone of a because the objects don't have the same type. So this (your example) is not cloning.
One easy way would be to use a json mapper (Jackson or Gson) and write out the object as a string and then creating the clone object by using the string.

Java: Creating a subclass object from a parent object

Newbie Java question. Say I have:
public class Car{
...
}
public class Truck extends Car{
...
}
Suppose I already have a Car object, how do I create a new Truck object from this Car object, so that all the values of the Car object is copied into my new Truck object?
Ideally I could do something like this:
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck(c);
/* would like t to have all of c's values */
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Yes, just add a constructor to Truck. You will probably want to add a constructor to Car also, though not necessarily public:
public class Car {
protected Car(Car orig) {
...
}
public class Truck extends Car {
public Truck(Car orig) {
super(orig);
}
...
}
As a rule it's generally best to make classes either leaf (and you might want to mark those final) or abstract.
It looks as if you want a Car object, and then have the same instance turn into a Truck. A better way of doing this is to delegate behaviour to another object within Car (Vehicle). So:
public final class Vehicle {
private VehicleBehaviour behaviour = VehicleBehaviour.CAR;
public void becomeTruck() {
this.behaviour = VehicleBehaviour.TRUCK;
}
...
}
If you implement Cloneable then you can "automatically" copy an object to a instance of the same class. However there are a number of problems with that, including having to copy each field of mutable objects which is error-prone and prohibits the use of final.
If you are using Spring in your project you may use ReflectionUtils.
Yes, you have to do this manually. You'll also need to decide how "deeply" to copy things. For instance, suppose the Car has a collection of tyres - you could do a shallow copy of the collection (such that if the original object changes the contents of its collection, the new object would see the change too) or you could do a deep copy which created a new collection.
(This is where immutable types like String often come in handy - there's no need to clone them; you can just copy the reference and know that the contents of the object won't change.)
Would I have to write my own copy constructor? This would have to be
updated everytime Car gets a new field...
Not at all!
Try this way:
public class Car{
...
}
public class Truck extends Car{
...
public Truck(Car car){
copyFields(car, this);
}
}
public static void copyFields(Object source, Object target) {
Field[] fieldsSource = source.getClass().getFields();
Field[] fieldsTarget = target.getClass().getFields();
for (Field fieldTarget : fieldsTarget)
{
for (Field fieldSource : fieldsSource)
{
if (fieldTarget.getName().equals(fieldSource.getName()))
{
try
{
fieldTarget.set(target, fieldSource.get(source));
}
catch (SecurityException e)
{
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
break;
}
}
}
}
you can use reflection i do it and work fine for me:
public Child(Parent parent){
for (Method getMethod : parent.getClass().getMethods()) {
if (getMethod.getName().startsWith("get")) {
try {
Method setMethod = this.getClass().getMethod(getMethod.getName().replace("get", "set"), getMethod.getReturnType());
setMethod.invoke(this, getMethod.invoke(parent, (Object[]) null));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//not found set
}
}
}
}
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Essentially, yes - you can't just convert an object in Java.
Fortunately you don't have to write all the code yourself - look into commons-beanutils, specifically methods like cloneBean. This has the added advantage that you don't have to update it every time it gets a new field!
You could always use a mapping Framework such as Dozer. By default (without further configuration), it maps all fields of the same name from one object to another using the getter and setter methods.
Dependency:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
Code:
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
// ...
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck();
Mapper mapper = new DozerBeanMapper();
mapper.map(c, t);
/* would like t to have all of c's values */
You will need a copy constructor, but your copy constructor can use reflection to find the common fields between the two objects, get their values from the "prototype" object, and set them on the child object.
You could use the reflection API to loop through each of the Car fields and assign the value to the equivalent Truck fields. This can be done within truck. Further it is the only way to access the private fields of Car - at least in an automatic sense, providing that a security manager is not in place and restricting access to private field.
The solutions presented above have limitations you should be aware of. Here's a short summary of algorithms for copying fields from one class to another.
Tom Hawtin: Use this if your superclass has a copy constructor. If it does not you will need a different solution.
Christian: Use this if the superclass does not extend any other class. This method does not copy fields recursively upwards.
Sean Patrick Floyd: This is a generic solution for copying all fields recursively upwards. Be sure to read #jett's comment that a single line must be added to prevent an endless loop.
I reproduce Sean Patrick Floyd's analyze function with the missing statement:
private static Map<String, Field> analyze(Object object) {
if (object == null) throw new NullPointerException();
Map<String, Field> map = new TreeMap<String, Field>();
Class<?> current = object.getClass();
while (current != Object.class) {
Field[] declaredFields = current.getDeclaredFields();
for (Field field : declaredFields) {
if (!Modifier.isStatic(field.getModifiers())) {
if (!map.containsKey(field.getName())) {
map.put(field.getName(), field);
}
}
}
current = current.getSuperclass(); /* The missing statement */
}
return map;
}
I know this is an OLD question, but I hate to leave out dated answers when things have improved.
Using JSON is much easier. Convert it to JSON and back again as child.
Here is an Android Kotlin Example.
val gson = Gson()
val childClass = gson.fromJson(
gson.toJson(parentObject),
object: TypeToken<ChildObject>(){}.type
) as ChildObject
I think in Java it would be basically.
Gson gson = new Gson()
ChildObject child = (ChildObject) gson.fromJson(
gson.toJson(parentObject),
TypeToken<ChildObject>(){}.getType()
)
And you're done, no messiness, just simple json in, json out.
If you don't have gson, I'm sure you have other json options available to you.
It's a WHOLE lot cleaner and faster than doing reflection and all that craziness.

Categories