I'm a C\C++ programmer just starting on Java.
I came across this working Java snippet syntax that I understand what it does but I can't understand the logic of the syntax.
object x = new object
.SetContent(aaa)
.SetIcon(bbb)
.SetText(ccc);
I get that the equivalent C++ code is:
object* x = new object;
x->SetContent(aaa);
x->SetIcon(bbb);
x->SetText(ccc);
Can anyone explain to me the logic in the Java syntax?
Is this something like the Visual Basic's With Statement?
P.S.
Don't think it matters but the Java snippet is from an Android program.
Those chain calls are possible because each setter method returns a reference to this:
public object SetContent(final String input){
this.aaa = input;
return this;
}
This is method chaining in java, where each method returns the current instance so that you can invoke the next method on current returned object from that method.
It's method chaining, where each method invocation returns the object it was invoked on. It's very common to see in Java when creating an object with a Builder, e.g.
Foo foo = FooBuilder.builder()
.setBar("bar")
.setVolume(11)
.setAnswer(42)
.build();
Where each .set___() method returns the updated builder object, and the final build() call returns the actual Foo instance. It would be perfectly equivalent to do this:
FooBuilder builder = FooBuilder.builder();
builder = builder.setBar("bar");
builder = builder.setVolume(11);
builder = builder.setAnswer(42);
Foo foo = builder.build();
But IMO the first version is much more readable. I'm not much of a C++ guy but I think you can do the same thing there.
EDIT: Here's a real life example:
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableSet.Builder.html
This syntax is creating the 'x' object, you should know that objects are references in Java.
this syntax is equivalent to:
private object x = new object();
x.setContent(aaa);
x.setIcon(bbb);
x.setText(ccc);
so first it create the object and then it calls each method.
The instance of that Object is returned by each of the methods called,the next subsequent method uses that returned instance to operate further. This is internally done by returning this .
Example:
Object methodFirst(Object ob1)
{
ob1.doSomeOperations();
return this;
}
Object methodSecond(Object ob1)
{
ob1.doSomeOtherOperations();
return this;
}
the above methods can be called like :
Object newObject = oldObject.methodFirst().methodSecond();
A more comprehensive and deep explanation can be found here
Related
I came across the below code in a Groovy project:
payloadDetails?.with {
payloadDetails.ardome.material_id = testAsset.materialId.trim()
payloadDetails.ardome.itm_id = testAsset.itemId.trim()
payloadDetails.ardome.mob_id = testAsset.mobId.trim()
payloadDetails.ardome.min_id = testAsset.minId.trim()
payloadDetails.ardome.original_ardome_filename = testAsset.originalFileName.trim()
}
where 'payloadDetails' variable is the return value of below (Map I assume):
static Map getCreateIndexPayload(String payloadName = 'CreateIndexPayload') {
//some code
}
So ? is the null safe operator, but what is the .with() method?
It looks like it's a method that allows reassigning Map's all or partial value member one by one. But I am not able to find this .with() definition in Map's interface document, or is it a method of Collection interface?
Is API documentation available for this method?
Object#with is a Groovy extension method that is available on any object. It takes a closure as a parameter and returns the closure's value. (For an equivalent that returns the original object, use tap; this is useful for nested initializations.)
In this case, the value of the closure (testAsset.originalFileName.trim()) is discarded, so the with simply has the effect of executing the closure against the object.
Note that the with and tap methods delegate to the target (that is, any assignments or method calls are resolved against it first), so the payloadDetails inside the closure is unnecessary and potentially a bug. Instead, you should be able to just say
payloadDetails?.with {
ardome.material_id = testAsset.materialId.trim()
ardome.itm_id = testAsset.itemId.trim()
ardome.mob_id = testAsset.mobId.trim()
ardome.min_id = testAsset.minId.trim()
ardome.original_ardome_filename = testAsset.originalFileName.trim()
}
or, if ardome is a POJO and not a nested map*,
payloadDetails?.ardome?.with {
material_id = testAsset.materialId.trim()
itm_id = testAsset.itemId.trim()
mob_id = testAsset.mobId.trim()
min_id = testAsset.minId.trim()
original_ardome_filename = testAsset.originalFileName.trim()
}
* or maybe if it is a nested map; you would need to try this yourself
1) In Java, I can do this:
Void z = null;
Is there any other value except null I can assign to z?
2) Consider the following code snipped:
Callable<Void> v = () -> {
System.out.println("zzz");
Thread.sleep(1000);
return null;
};
This compiles OK, but if I remove the last statement return null; it doesn't. Why? After all, Void is supposed to mean no return value.
From the docs:
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.
So, no.
Void is used by methods having to return an object, but really returning nothing.
A decent example can be observed with some usage of the AsyncTask in Android, in cases where you don't need to return any object after the task is complete.
You would then extend AsyncTask<[your params type], [your progress type], Void>, and return null in your onPostExecute override.
You wouldn't need it in most cases though (for instance, Runnable is typically more suitable than Callable<Void>).
Ansering your question more specifically:
But if I remove the return null it does not compile?! Why?
... because a Void is still an object. However, it can only have value null.
If your method declares it returns Void, you need to (explicitly) return null.
If you check the sources:
package java.lang;
public final class Void {
public static final Class<Void> TYPE = Class.getPrimitiveClass("void");
private Void() {
}
}
Void is:
final class;
has private constructor.
Without using Reflection it's not possible to assign anything but null to a reference of Void type.
In Java, I can do this Void z = null; Is there any other value (but null) which I can assign to z ?
You can if you create you own Void instances. You can use Reflection or Unsafe to create these, not that it's a good idea.
But if I remove the return null it does not compile?! Why? After all, Void is supposed to mean just that - no return type.
Java is case sensitive, this means that Boolean and boolean are NOT the same type nor is Void and void. Void is a notional wrapper for void but otherwise is just a class you shouldn't create any instance of.
Maybe what you are asking for is Runnable or Consumer - some interface that doesn't have a return value. Void only serves to show that you cannot expect anything else than null. It is still just a class, not a keyword or anything special. A class that cannot be instantiated, so you have to return null.
A lot of efforts were spent in designing lambda expression to treat int/Integer etc indistinguishably, so that int->Long will be compatible with Integer->long, etc.
It is possible (and desirable) to treat void/Void in a similar way, see comments from Goetz and Forax.
However, they didn't have the time to implement the idea for java8 :(
You can introduce an adapter type that is both ()->void and ()->Void; it can simplify your use case a little bit, see http://bayou.io/release/0.9/javadoc/bayou/util/function/Callable_Void.html
If you have a method that accepts ()->Void, it is not going to work well with ()->void lambdas. One workaround is to overload the method to accept ()->void. For example, ExecutorService
submit(Callable<T> task)
submit(Runnable task)
...
submit( System::gc ); // ()->void
However, overloading with functional parameter types is tricky... The example above works because both accept a zero-arg function. If the function has non-zero args
foo( Function<String,Void> f ) // String->Void
foo( Consumer<String> f ) // String->void
it's confusing to the compiler (and the programmer)
foo( str->System.out.println(str) ); // which foo?
foo( System.out::println ); // which foo?
Given an implicit lambda str->expr, the compiler needs a target type to make sense of it. The target type here is given by the method parameter type. If the method is overloaded, we need to resolve method overloading first... which typically depends on the type of the argument (the lambda)... So you can see why it is complicated.
(A zero-arg lambda is never implicit. All argument types are known, since there's no argument.)
The lambda spec does have provisions to resolve the following cases
foo( str->{ System.out.println(str); } );
foo( str->{ System.out.println(str); return null; } );
You may argue that in the previous example,
foo( str->System.out.println(str) );
since println(str) returns void, the Void version obviously does not fit, therefore the compiler should be able to resolve it. However, remember that, to know the meaning of println(str), first, the type of str must be resolved, i.e. method overloading of foo must be resolved first...
Although in this case, str is unambiguously String. Unfortunately, the lambda designer decided against to be able to resolve that, arguing it is too complicated. This is a serious flaw, and it is why we cannot overload methods like in Comparator
comparing( T->U )
//comparing( T->int ) // overloading won't work well
comparingInt ( T->int ) // use a diff method name instead
What I want to achieve is something like this:
MyClass object = null;
doStuff(&object);
// `object` can now be non-null
What I'm currently doing is this, but I think there must be a better way to achieve this behavior in Java:
MyClassPointer pointer = new MyClassPointer(null);
// pointer.object is null
doStuff(pointer);
// pointer.object can now be non-null
If you really want doStuff to return two values: There may well be a better way to design this. Nevertheless, if you've decided that having doStuff return two values is really the best design, it can be done with a simple helper class:
static class MyClassAndBoolean {
public MyClass obj;
public boolean b;
public MyClassAndBoolean(MyClass obj, boolean b) { this.obj = obj; this.b = b; }
}
and then change doStuff's return type to MyClassAndBoolean. This is one of the very few cases where I think public fields in a class are OK. Since you're defining a simple class just to use as a function result, rather than representing a coherent concept, the usual concerns about defining accessors instead of exposing fields, etc., don't really apply. (P.S. I just guessed at boolean for the other type, but it can be anything, of course.)
Another workaround:
MyClass[] obj = new MyClass[1];
result = doStuff(obj);
Change doStuff's parameter type to MyClass[], and have it stuff the new object into parameter[0]. I do see this idiom used in some of the Java and Android library methods.
Why not simply:
MyClass object = doStuff();
which is much more intuitive IMHO. Otherwise you have to pass a reference (not pointer!) to a container object to your method, as you've identified. That's not a common pattern in the Java world.
As far as I know java language it is the only way to do that.
But you can simply implement method into your class. And in your method also there is possibility to return your object.
public MyObject myFunction(){
//do stufff...
return new MyObject();
}
MybObject object = myFucntion();
Or you can do it in your way. Also using Reflection you can invoke your method.
Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);
No, there is no better way since in Java you don't have pointers the way you have them in C++.
In Java references (much like pointers in C++) can't be directly accessed and are always passed by value. Thus you can't change the value of a reference within a method.
Use the Visitor pattern, your MyClass being what have to be 'visited' by dostuff
I'm working in some Java code and I have a doubt. I have a loop that goes along a Collection to modify each one of its objects with a method. The thing is, when you pass an object to a method, what are you really passing? A copy of the reference? the memory address? Here is my code:
for(Iterator it = colDesglosesBDI.iterator(); it.hasNext();)
{
DesgloseBDIVO desgloseBDI = (DesgloseBDIVO)it.next();
desgloseBDI = completeDesgloseAgrup(desgloseBDI);
}
The method completeDesgloseAgrup returns a DesgloseBDIVO Object so I can replace the old objects with the new attributes. But maybe I can do it by this way:
for(Iterator it = colDesglosesBDI.iterator(); it.hasNext();)
{
DesgloseBDIVO desgloseBDI = (DesgloseBDIVO)it.next();
completeDesgloseAgrup(desgloseBDI);
}
And in this case the method would be void and do not return any object. Is possible to do it in that way?
Regards
Yes that is entirely possible provided the completeDesgloseAgrup() method only changes the attributes of the argument, and does not try to replace it with a new object.
Consider this:
public void completeDesgloseAgrup( DesgloseBDIVO d )
{
// will work, callee will see "something"
d.setSomething( "something" );
}
public void completeDesgloseAgrup( DesgloseBDIVO d )
{
// Won't work, as Java has call by value semantics. Callee won't see the new DesgloseBDIVO in callee's scope.
d = new DesgloseBDIVO()
d.setSomething( "something" );
}
Cheers,
In java objects are data structures on the heap which you reference by variables, hence you never pass the objects, always the reference to an object.
From "The Java Programming Language, 4th edition" by Ken Arnold, James Gosling and David Holmes:
The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing mode pass by
value and that helps keep things simple.
Im having trouble figuring out how to implement the equivalent of overloading the assignment operator in C++ to Java. I know there is no such thing, but I need to simulate it. I've tried overriding the Clone() function, but no luck. Any ideas?
Below is my main
Queue p = new Queue();
Queue q = new Queue();
p.enqueue('a');
p.enqueue(9);
p.enqueue(10);
p.enqueue(310);
p.enqueue(8);
q = p;
System.out.print(p);
And here is the clone function
public void Clone(Queue other) throws Throwable
{
System.out.println("test\n");
if(this == other)
{
}
else
{
while(!isEmpty())
dequeue();
Node tmp = other.head;
while(tmp != null){
this.enqueue((T)tmp.element);
tmp = tmp.next;
}
}
}
Operator overloading is Not supported by Java.
Operator overloading violates one of the central tenets of the Java language design : transparency. It is against the language philosophy trying to overload an operator and should be avoided ...
Operator overloading cannot be done in Java. It requires support from the compiler to do just that. You can however create a preprocessor that understands java syntax and run it before building, that converts the call of your operator to an appropriate function but that is just overkill.
clone is not not related to operator overloading.
You're going to need to write an explicit copy constructor. In Java, everything's a pointer (or "reference" as they call them), so when you assign p to q, you're just saying that p and q point to the same object.
q = new Queue(p)
Is what you want, assuming you've implemented the appropriate constructor.
EDIT:
What you're proposing is just not possible with the syntax "q = p". If you want to "simulate" the assignment operator, then you're going to need to write a new method in Queue. For example, here's how Java programmers "simulate" overloading the addition operator:
a.add(b);
So in your case you'll need to write an "assign" method that takes a Queue, copies its data, and assigns these copies to the internal data of the other object.
q.assign(p);
public void assign(Queue other) {
this.primitive = other.primitive;
this.someObject = new SomeObject(other.someObject);
}
That's about as close as you're going to get.
There is no "equivalent" because you cannot overload the assignment operator in Java. You're attempting to imitate the behavior with the clone() method, but you've got it backwards. Without operator overloading, you have three options:
Write a function that mutates the invoking object to become a copy of the one passed in.
Write a function that makes a copy of the invoking object and returns it to something else that will store it.
Use a copy constructor.
1. Write a function that mutates the invoking object to become a copy of the one passed in.
Note that this is identical to the assignment operator overload, except it's named "copy" instead of "operator=".
If you want to do this:
foo A;
foo B;
A.copy(B); // A is now a copy of B.
In C++:
foo& copy(const foo& rhs)
{
if(&rhs != this)
{
this->m_someInt = rhs.m_someInt;
this->m_someBar = rhs.m_someBar;
}
return *this;
}
In Java:
foo copy(foo rhs)
{
this.m_someInt = rhs.m_someInt;
this.m_someBar.copy(rhs.m_someBar);
return this;
}
Note that in C++, assigning this->m_someBar to rhs.m_someBarcopies rhs.m_someBar by value, but in Java such an assignment would cause both foo objects to share the same Bar object. Therefore, a similar copying mechanism must be used on your subojects as well if you don't intend for them to be shared.
2. Write a function that makes a copy of the invoking object and returns it to something else that will store it.
If you want to do this:
foo A;
foo B;
A = B.clone(); // A is now a copy of B.
In C++:
foo clone() const // Ignoring the fact that this is unnecessary in C++ where assignments (and returns) are by-value anyway.
{
foo theCopy;
theCopy.m_someInt = this->m_someInt;
theCopy.m_someBar = this->m_someBar;
return theCopy;
}
In Java:
foo clone()
{
foo theCopy = new foo();
theCopy.m_someInt = this.m_someInt;
theCopy.m_someBar = this.m_someBar.clone();
return theCopy;
}
3. Use a copy constructor.
If you want to do this:
foo B;
foo A = new foo(B); // Java version
foo A(B); // C++ version
In C++:
foo(const foo& rhs)
:m_someInt(rhs.m_someInt), m_someBar(rhs.m_someBar)
{
}
// Or optionally:
foo(const foo& rhs) = default;
In Java:
foo(foo rhs)
{
m_someInt = rhs.m_someInt;
m_someBar = new Bar(rhs.m_someBar);
}
In conclusion, your issue is that you're trying to use clone() in the same way I use copy() above. The closest to an equivalent would be my copy method. My personal suggestion is to just use a copy constructor and call it a day.
If you're trying to override the clone method on Object, it needs to have the same signature (and capitalization). Your method signature is Clone(Queue).
It's not really clear how this relates to trying to simulate operator overloading though, or what operator you're trying to overload...
I'm from a C++ background so I know where you are coming from.
I think it is the clone method you are after. Don't forget to implement the Cloneable interface to tell 'Object' that this object is a cloneable object. See Effective Java (2nd Ed) item 11 for a thorough explanation.