Java equivalent of C++ copy assignment operator - java

I'm trying to understand this operator function written in C++ and convert it to Java.
Class& Class::operator=(const Class& In) {
properties = In.properties;
return *this;
}
Does this simply copy instance and properties of a class object? For which I've already written something:
public static Class copy(Class obj) {
//returns new instance of Class individual
Class copy = new Class(obj.row_num, obj.col_num, obj.input_length, obj.output_length, obj.max_arity, obj.function_length, obj.levels_back);
copy.genes = obj.genes.clone();
return copy;
}
Am I on the correct track? Many thanks for your help.

Ampersand & designates a reference in C++. It is needed to provide the behavior similar to what Java objects provide "out of the box", because Java manages objects through references.
There is no copying going on in C++ when a reference is passed. In fact, avoiding copying is a major reason for using const references as function parameters.
The code that you show does not perform copying either: it changes its state based on the value being "assigned". The closest way of modeling this in Java would be providing an assign(Class other) method that changes the current state to match that of the object passed in:
Class assign(Class other) {
this.properties = other.properties;
return this;
}
You will need to use this method in place of C++'s assignment, like this:
Class clOne(args1);
Class clTwo(args2);
clOne = clTwo; // Using the assignment operator
becomes this:
Class clOne = new Class(args1);
Class clTwo = new Class(args2);
clOne.assign(clTwo); // Using the assignment method instead of the operator

You're pretty much on the right track. The copy assignment operator in C++ is used when directly assigning (copying) from one object to another. As Java objects are only accessible via references, such assignments are meaningless. To match the C++ semantics exactly, the Java equivalent would be:
public Class copy(Class obj) {
row_num = obj.row_num;
col_num = obj.col_num;
// etc., etc.
genes = obj.genes.clone();
return this;
}

Am I on the correct track?
Kind of. But not quite. C++ distinguishes between reassigning an existing object and creating a new one.
Java doesn’t. You cannot reassign to an existing object in Java1 (but you can of course reassign a reference). In Java, in order to copy an object (rather than assign a reference to it), you would usually use a copying constructor:
Class(Class other) {
// Copy members of `other` into `this`.
}
And then use it as follows:
Class x = new Class(something here);
Class y = new Class(x); // copy
In particular, this is what all the Java containers implement. I would not rely on clone. First of all, clone should only be used if the class implements the tag interface Cloneable. Second of all, clone’s design is arguably broken and its use is not recommended.
1 Well you could of course reassign the members of an object (unless they are final), and you could mimic C++’s copy assignment operator by providing a method assign to do that. However, this isn’t the conventional way of doing things in Java (although it might have its place in some exceptional instances).

Related

Create an inline object and pass as parameter

Hi I come from Java where the following is valid:
System.out.println(new String("Hello World"));
is there a C++ equivalent to passing creating an object or pointer in the constructor and pass it as a parameter at the same time such as.
heap.insert(new Food);
Yes. For example
std::vector<Food> c;
c.emplace_back(constructor arguments for Food);
In general, it is most often the case that objects are not given to method as pointers.
If heap.insert takes a const reference :
void insert(const Food& val);
then you can use it with temporary or existing Food arguments, such as
heap.insert(Food{});
var auto foo = Food{constructor arguments};
heap.insert(foo);
heap.insert(Food(constructor arguments));
or in some cases even
heap.insert({constructor arguments});
heap.insert(new Food);
in of itself is valid C++ syntax. It constructs a new instance of the Food class, and passes it to heap's insert() method.
However, the key fundamental difference you will need to learn when transitioning from Java to C++ is that your C++ application is completely responsible for managing all object's lifetimes. In Java you don't need to think about it. Once an object is no longer referenced anywhere, at some point it'll get destroyed by Java's garbage collector.
C++ makes you responsible for managing each object's lifetime. Whenever your application does not need the object that you constructed here with the new operator, it should be deleted, otherwise you're going to leak memory.
To summarize:
heap.insert(new Food);
is just half the story. The new operator will construct your new class instance, and your heap object's insert() method, presumably, stores the pointer to the new class instance, in some fashion. Somewhere, you will then need to delete that class instance, sooner or later.
Yes. You have to define a class, a constructor for it that accepts parameters, then a function that accepts instances of that class and that's all.
Eventually, add to the class definition a proper copy constructor or pass it by reference.
It follows an example:
struct S {
S(int x) { this->x = x; }
int x;
};
void fn(S s) { }
void cfn(const S &s) { }
int main() {
fn(S{42});
cfn(S{42});
}
Be aware that using new in such a case is one of the easiest ways to incur in a memory leak, so pay attention!!
The examples you gave are too easy.
cout << string("hello World");
// not necessary to contruct a string, but to show that it can be done on the spot
heap.insert(Food()); // construct a Food on the spot...
But in general, if you are talking about anonymous classes and similar things in Java, C++ has this stuff, and it has also the lambda concept which is very powerful ;)
If the function parameter is by value or by const reference, and the type you are passing can be used to construct the object, you can pass it directly. For example:
void print(const std::string& str);
int main()
{
print("Hello world");
}
std::string has a constructor which can accept the string literal, and therefore the code compiles, creating a temporary string object, equivalent to:
print(std::string("Hello world"));
If the constructor takes multiple parameters, you can create a temporary object directly in the function call. For example:
void myfunc(const MyClass& c);
myfunc(MyClass(param1, param2));
In Java new objects are creating using new. In C++, new is not required to create a new object, and should be avoided as much as possible, because it makes it harder to avoid memory leaks. This is one of the most common mistakes programmers coming from Java make.
std::string text;
MyClass c;
c.do_something();
This code is totally valid. text and c are valid objects.
std::string *text = new std::string();
MyClass *c = new MyClass();
c->do_something();
delete text;
delete c;
This code is also valid*. But it takes more typing, and if you forget to delete them, you will get a memory leak.
*Edit: Actually it is not exception safe! All the more reason to avoid new!

Best strategies when calling a method that should modify more than one variable

I am pretty new to Java, I have to convert C/C++ code to Java and I am running into obstacles. Because of the way variables are passed to the methods, their modification in the method is not straightforward, and I have no idea what is the most reasonable approach to take. Sorry for the pseudocode examples, I hope they will clearly explain what I am talking about without delving into unnecessary details.
I need something that would be equivalent to C
ModifyMyString(type1 &t1,type2 &t2);
(return type doesn't matter, it can be void) as I need the function to modify both t1 and t2.
I can easily modify one of the variables, say t1, by declaring in Java
type1 modifyMyString(type1 t1, type2 t2);
and assigning the returned value to
t1 = modifyMyString(t1,t2);
but it is only half of a success, as the new value of t2 is lost.
I can declare new class
class JustToPassTwoVariables {
type1 t1;
type2 t2;
JustToPassTwoVariables(type1 tt1, type2 tt2) { t1 = tt1; t2 = tt2; }
}
and do something like
JustToPassTwoVariables jtptv = modifyMyString(JustToPassTwoVariables(t1,t2));
but I feel like it is clumsy and makes the code unreadable.
In desperation I could also resign the idea of using a modifyMyString method, and repeat all the code locally in each place I would call modifyMyString - but it makes even less sense than using JustToPassTwoVariables class.
Is there a correct (or at least widely used, accepted as a standard, whatever) strategy to code such things in Java?
The recommended way in java is (in some people's opinion the clumsy way) to create a class containing the two fields and return an instance of that class.
I feel that it is much less clumsy if you stop and think about what the method is actually doing, and taking care to properly name both the method and the class returning the two values.
The simple answer is no. This sort of feature is not allowed in Java.
The correct way to do it is to pass in the object to be modified not the two variables. After all in virtually all cases those variables are already wrapped in an object, in cases where they aren't they often easily can be.
Either split the function into two functions and call it once for each variable, or wrap the variables into an object and pass that object into the function.
Don't forget Java allows Inner Classes which makes this sort of thing less painful.
You can't return two values from a method in java. The way is to return an object and set all the values in it. i.e. In your case, you need to create a value container class i.e. say Result class that will have two fields storing the type1 and type2 value in it. The return type of the method would be of value container object type i.e. say Result instance with two fields in it - type1 and type2
Example :
Result result = modifyMyString(t1,t2);
result.getT1(); //gets t1 value
result.getT2(); // gets t2 value
Please learn about setters and getters in Java to work on the class or object level fields
In Java if you want to do this you would generally make type1 and type2 into object whose values can be modified. The method can then modify the values of the parameters to get the desired effect. For example :
void myMethod(type1 arg0, type2 arg1) {
arg0.setValue(newValue0);
arg1.setValue(newValue1);
}
If type1 and/or type2 do not have any way of changing their values (e.g. they are of type String) then you would either make a wrapper class for each of them e.g.
class Type1Wrapper {
private type1 type1;
type1 getType1() {
return type1;
}
void setType1(type1 newType1) {
type1 = newType1;
}
}
or you would make a wrapper for both of the types simultaneously like you have in your question (although the method return type will be void and the method will modify your wrapper's values)
There are several methods to modify a group of objects "of the same type/class". The simplest of them being, add them to a "list" pass that list to your modification function, do whatever modifications/additions/deletions etc.. The list reference will be automatically available outside with the "changes made in the called function" .
So, you can do
List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("world");
ModifyMyString(l);
// here also l = "hello" , "world" , "added"
public void ModifyMyString(List l)
{
l.add("added"); // now l = "hello" , "world" , "added"
}
Java is an OO language so to get the best out of it you should look to an OO solution. It's hard to give you a definite solution with this abstract example but this is how I would approach this.
You mention that t1 and t2 both need to be updated by this modify procedure/method. Also that they need to be updated at the same time, if they were unrelated then you could just call modify on each string in turn. If these two strings are related like this then it's likely they belong to the same type.
So we need a class containing type 1 and type 2.
public class TypeContainer
{
private String type1;
private String type2;
.. getters and setters
}
Obviously you'll want a better class name.
You suggest something similar yourself but call it JustToPassTwoVariables. This is missing the point of OO. You could write a simple wrapper like this and pass it to some other method to modify the values but a more OO approach would be to add the modify method to this class itself.
...
public void modfiy(String val1, String val2)
{
type1 = val1;
type2 = val2;
}
...
I'm not sure what your modify is trying to do but in this case I would probably have these as two separate setter methods. This is quite an abstract example!
Basically I would avoid having the modify method in some other unrelated class. You should look to group common related attributes into classes and then write methods in those classes for any actions you need to take (such as modify).
Trying to convert a procedural C program into an OO Java program sounds like a PITA. It's a complete paradigm shift. Having said that I have seen automated conversions which while technically Java are still very procedural. Not very pretty and hard to maintain but was done for political reasons.
Java discourages this strategy beacause in-variable should be immutable, but if you have to migrate from C/C++/C# and you have a lot of "void function with parameters passed as in/out", you can create a Custom "Reference" class like this and you can incapsulate the original object.
public class CustomRef {
public Object internal;
public CustomRef(Object object) {
this.internal=object;
}
}
then when you call
CustomRef ref1= new CustomRef(myParams1);
CustomRef ref2= new CustomRef(myParams2);
myFunction(ref1, ref2);
myParams1 = ref1.internal;
myParams2 = ref2.internal;
the function is
void myFunction(CustomRef ref1, CustomRef ref2) {
Object param1 = ref1.internal
// a lot of code
ref1.internal = param1;
}
really discouraged way ... such as using ArrayList, arrays [] to "pass by reference".
NOTE: this way is a waste of resource; CustomRef instance should be reused through object pool (another discouraged way).
I would use a StringBuffer. You can initialize it with a String and convert it back to a String

Method runs for all instances of a class

I ran across this problem, which has been driving me nuts. In a nutshell, I instantiate two objects of the same class. When I run a method in one object, the other object is affected too as if I called a method on a 2nd object explicitly. I was wondering if someone could please give me a hand on this.
Suppose, I have class Portfolio...
public class Portfolio implements Cloneable {
public ArrayList<Instrument> portfolio;
private String name;
private String description;
public Portfolio() {
portfolio = new ArrayList<Instrument>();
}
public Portfolio(Portfolio copyFrom) {
//attempt to copy the object by value
this.portfolio = (ArrayList<Instrument>) copyFrom.portfolio.clone();
this.name = copyFrom.name;
this.description = copyFrom.description;
}
public void applyStress(Stress stress) {
this.portfolio.set(0,this.portfolio.get(0)+1;
}
1st constructor is used to instantiate an object, etc. 2nd constructor is used to copy an object by value.
A method applyStress is used to run through sum calculations. in our case I simplified the method, so that it does nothing but adds +1 to whatever is in the object.
So I would instantiate an object as
Portfolio p = new Portfolio();
then I would assign to a portfolio field, some instruments;
p.portfolio = someInstrumentList;
then I would copy by value the portfolio p into pCopy:
Portfolio pCopy = new Portfolio(p);
So at this time I am have two objects that are the same. Further one is a copy-by-value object. Changing values of fields in pCopy does not affect same fields in p.
Now, when I run a method applyStress on p, then the values of the instrument list in pCopy will also change.
In other words, if p.portfolio.get(0) == 1, then after p.applyStress, I would expect to see that p.portfolio.get(0) is 2 and pCopy.portfolio.get(0) is 1
But what I see instead is p.portfolio.get(0) is 2 and pCopy.portfolio.get(0) is also 2
I do not understand why this happens. It is not the static modifier issue, as there is no static modifiers. Anyone has any ideas?
The clone method applied to you your ArrayList reference does a shallow copy, not a deep copy. This implies that whatever you had in the original collection is shared by the cloned one.
This means that you need to clone every instrument as well, or provide a copy constructor for every one of them.
this.portfolio = new ArrayList<Instrument>();
for(Instrument toBeCopiedInstrument : copyFrom.portfolio){
this.portfolio.add(new Instrument(toBeCopiedInstrument ));
}
By default .clone() does what is called a shallow copy, this means it just copies a reference to the objects that are held in the List that is being cloned, it doesn't actually copy the objects themselves to new instances.
What you need to do is implement a custom deep copy for the List and each of the items held in the list. But deep clone is a broken concept and implementation in Java.
A copy constructor isn't a really good pattern in Java either, because you end up copying references as well in most cases and every object you inject to the constructor has to follow the same copy constructor semantics all the way down the chain. Unlike C++, this is manual, tedious, unmaintainable and error prone process!
.clone() and implements Cloneable are some of the most complex to get correct concepts in Java. They are rarely needed in well designed applications. That is, if you are using .clone() you are probably doing it wrong. If making bit wise copies of your objects are part of your design for something other than storage, you might want to revisit your design.
Josh Bloch on Design
Object's clone method is very tricky. It's based on field copies, and
it's "extra-linguistic." It creates an object without calling a
constructor. There are no guarantees that it preserves the invariants
established by the constructors. There have been lots of bugs over the
years, both in and outside Sun, stemming from the fact that if you
just call super.clone repeatedly up the chain until you have cloned an
object, you have a shallow copy of the object. The clone generally
shares state with the object being cloned. If that state is mutable,
you don't have two independent objects. If you modify one, the other
changes as well. And all of a sudden, you get random behavior.
Immutable
A better pattern is to make everything immutable. That way you don't need separate instances, you can share instances until they need to change, then they change and you have a new instance with the new data, that can be shared without any side effects.

`*this = rhs` in Java?

I'm coming from the C++ world and I can't find what is the Java alternative (if any) to the following:
struct SomeStruct
{
SomeStruct(){}
SomeStruct(const SomeStruct& rhs)
{
*this = rhs;
}
};
The reason why I need this is that I have a cache of existing objects, so I don't want to create another instance but just to 'clone' the existing one, something like this:
public class SomeObject
{
private static Hashtable _objects;
SomeObject()
{
SomeObject obj = _objects.get(some_key);
if (obj != null) {
// *this = obj;
// instead of:
// this.something = obj.something;
// this.something1 = obj.something1;
// this.something2 = obj.something2;
// a zillion fields....
}
}
};
EDIT:
Sorry, I confused some things (still need to learn both Java and C++).
Thank You
The closest is Object.clone() but read the relevant section from Effective Java first.
There are probably simpler ways to do what you want if you remove some of your requirements. For example, if you make your objects immutable then you don't need to copy the data into another object. Instead you can return a reference to the original object. This is much faster than a memberwise copy, and has lots of other benefits too, such as making it easier to write thread-safe code.
There's no direct equivalent. Object.clone() is the closest, but it creates a new instance and performs a shallow copy. You could write something generic using reflection though.
public class SomeObject
{
private static Hashtable _objects;
public static SomeObject getInstance(SomeKey some_key)
{
return _objects.get(some_key);
}
}
It is unclear from your question whether you are trying to achieve a pure cache of immutable objects, or keep a cache of 'template' objects, and return copies that can then be mutated by the client. I am going to assume the latter.
Assuming that you do want to return copies of originals. there is no really nice way to implement a copy constructor in Java. Clone is marginally nicer, so you should hide the constructor behind a static factory method:
public static SomeObject getInstance(...) {
SomeObject cached = ...;
if (cached != null) {
return cached.clone();
}
...
}
Perhaps in your particular case you can separate the immutable and stateful parts of the objects? If so, some changes to your object model can lead to cleaner (and more efficient) code?
In Java, if you want to have a constructor corresponding to a copy constructor, you have to implement it yourself. In some cases, this means you have to copy fields from one object instance into another, while in other cases it means you have to implement a full deep copy - recursively iterate through the reference fields of the parameter in the copy ctor.
This depends on what you want - should the objects hashtable be copied as well? Or should both objects share the reference to it? For more info, see this question.
I don't know of any generic way to copy all the contents of fields from one object to another existing without using;
reflections
generated code.
copy using the Unsafe class.
Reflections is easier to use at runtime, but not as efficient as generated code. (But pretty close) I generate my data model so I use this option.
The Unsafe class is faster than reflection, but not cross platform and unsafe. It is almost as fast as generated code. ;)
In terms of speed, if generated code is 1x, Unsafe is 1.5 - 2x and reflection is 2 - 4x slower for highly cached data. For poorly cached data you won't see a difference.
You should use the Singleton pattern. You create a static instance of SomeObject and work with that instance.
private static class SingletonHolder {
public static final SomeObject INSTANCE = new SomeObject();
}
public static SomeObject getInstance() {
return SingletonHolder.INSTANCE;
}
But don't fall in the Singleton trap, limit calls to getInstance()!

Function didn't change the value - JAVA 6 SE

I can't understand why the overloaded function 'increase' does not change Integer but does change Point.
The propuse of 'Integer' class is to wrap int so it will be a reference Type.
import java.awt.Point;
public class test2 {
public static void main(String[] args) {
///1
Integer i = new Integer(0);
increase(i);
System.out.println(i);
///2
Point p = new Point(0,0);
increase(p);
System.out.println(p);
}
public static void increase(Integer i){
i = 1;
}
public static void increase(Point p){
p.setLocation(1, 1);
}
}
the output is :
0
java.awt.Point[x=1,y=1]
Also, is their a simple way to pass a variable to a function by reference in Java?
Integer class is an immutable class, that means its content can't be changed after it's created.
Also, Java is pass-by-value so the variable i is passed by value, and the fact that it changes inside the function has no effect on the caller.
Read here: http://en.wikipedia.org/wiki/Immutable_object for more information on immutable objects.
The simple answer is that Java uses pass by value, not pass by reference.
In the Point case, the method is changing a field of the point object whose reference was passed into the method.
In the Integer case, the method is simply assigning a new value to the local variable i. This does not update the variable i in the calling method, because Java uses pass by reference.
The other issue is that Integer has no setValue methods because it is immutable. If you want to do the equivalent of what the Point version of the method is doing, you will have to define an IntegerHolder class that has both a getter and a setter, together with methods such as increase, that your application needs. (Alternatively, find such a class in a 3rd party library.)
Integer objects are immutable, i.e. you can't change them. If you could, the syntax would be like
i.setValue(1);
If you want to pass a non-object by reference, you can either wrap it in an array of length 1 or (better) create a trivial wrapper. However, there is little reason to do so - don't port your code from C 1:1. Usually, you should have a semantically loaded object, like an Account on which you can call the increase and decrease (or maybe just setBalance) methods.
In this function:
public static void increase(Integer i){
i = 1;
}
autoboxing makes this equivalent to:
public static void increase(Integer i){
i = new Integer(1);
}
i.e. it changes the reference that i contains, not the value that it contains. The Integer object is itself immutable, there's actually no way to change the value of one after it has been created.
Since that reference is a local variable, any changes to it will not affect the variable that was passed in.
When you write i = 1, you are changing the i parameter to point to a new boxed Integer instance.
The original Integer instance that you passed to the function is not—and cannot be—changed—Integers are immutable
Answer here: http://www.javaworld.com/javaworld/javaqa/2000-06/01-qa-0602-immutable.html
This reference could be useful: http://javadude.com/articles/passbyvalue.htm
If you wanted the two methods to be equivalent, the second one would look like this:
public static void increase(Point p){
p = new Point(1, 1);
}
And then you would see that it outputs the original point here, too.
There is no pass a variable to a function by reference in Java.
You can simulate it by passing an object which contains the variable (like you did in your increase(Point) method) - you'll have to be sure to assign to the variable, though, not to the object containing the variable.
As said before, there are several "mutable wrappers" around (for example org.omg.CORBA.IntHolder and java.util.concurrent.AtomicInteger in the standard API), but it is not difficult to create your own, and in most cases it would be better to use a sensible "Business object" like an "Account" instead.

Categories

Resources