I have a question about boolean values in Java. Let's say I have a program like this:
boolean test = false;
...
foo(test)
foo2(test)
foo(Boolean test){
test = true;
}
foo2(Boolean test){
if(test)
//Doesn't go in here
}
I noticed that in foo2, the boolean test does not change and thereby doesn't go into the if statement. How would I go about changing it then? I looked into Boolean values but I couldn't find a function that would "set" test from true to false. If anyone could help me out that would be great.
You're passing the value of a primitive boolean to your function, there is no "reference". So you're only shadowing the value within your foo method. Instead, you might want to use one of the following -
A Holder
public static class BooleanHolder {
public Boolean value;
}
private static void foo(BooleanHolder test) {
test.value = true;
}
private static void foo2(BooleanHolder test) {
if (test.value)
System.out.println("In test");
else
System.out.println("in else");
}
public static void main(String[] args) {
BooleanHolder test = new BooleanHolder();
test.value = false;
foo(test);
foo2(test);
}
Which outputs "In test".
Or, by using a
member variable
private boolean value = false;
public void foo() {
this.value = true;
}
public void foo2() {
if (this.value)
System.out.println("In test");
else
System.out.println("in else");
}
public static void main(String[] args) {
BooleanQuestion b = new BooleanQuestion();
b.foo();
b.foo2();
}
Which, also outputs "In test".
You named your parameter the same as an instance variable. Here, the parameter is the one referenced, not the instance variable. This is called "shadowing", where the simple name test as a parameter name shadows the instance variable also called test.
In foo, you changed the parameter test to true, not the instance variable test, which was unchanged. That explains why it doesn't go into the if block in foo2.
To assign the value, get rid of the parameter on foo, or use this.test to reference the instance variable.
this.test = true;
and
if (this.test)
You need to be aware that:
In Java, arguments are pass-by-value.
Boolean, the wrapper type of boolean, is immutable.
Because of 1 and 2, you have no way to change the state of the Boolean pass in the method.
You mostly have 2 choice:
Choice 1: Have a mutable holder for boolean like:
class BooleanHolder {
public boolean value; // better make getter/setter/ctor for this, just to demonstrate
}
so in your code it should look like:
void foo(BooleanHolder test) {
test.value=true;
}
Choice 2: A more reasonable choice: return the value from your method:
boolean foo(boolean test) {
return true; // or you may do something else base on test or other states
}
the caller should use it like:
boolean value= false;
value = foo(value);
foo2(value);
This approach is preferrable as it fit better with normal Java coding practices, and by the method signature it gives hint to the caller that it is going to return you a new value base on your input
Here is a good explanation.
http://www.javadude.com/articles/passbyvalue.htm
Java has pointers, and the value of the pointer is passed in. There's
no way to actually pass an object itself as a parameter. You can only
pass a pointer (value) to an object.
And my solution
public static class MutableBoolean {
public boolean value;
public MutableBoolean(boolean value) {
this.value = value;
}
}
usage:
MutableBoolean needStop = new MutableBoolean(false);
call( new Listener(needStop){
void onCallback(){
needStop.value = true;
}
})
Your foo method changed the value of test to true. It looks like what you want is to use instance variables for each function.
boolean test = false;
...
foo(test)
foo2(test)
foo(Boolean test){
this.test = true;
}
foo2(Boolean test){
if(this.test)
//Doesn't go in here
}
This way, your method only changes the value of test inside of that method, but your public test parameter stays with a false value.
Related
I'm encountering problems understanding how function are passed to methods as parameters.
Searching on StackOverflow and StackExchange has brought me to a solution using java.util.Functions
public void someFunction(Functions <int[], int[]> myFunction);
(source: https://codereview.stackexchange.com/questions/186972/passing-a-generic-function-as-parameter)
Although this solution seems good to me, I'm facing problem when I need to pass a function which is intended to do nothing. For better understanding, consider the following example:
public class Example {
//do stuffs
myFunction(null);
}
public class Manager {
public void myFunction(Function<int[], void> funcToPass) { // Can't specify void as return value!
//do stuff
if(funcToPass != null) { // can't replicate such behaviour
funcToPass(someParams)
}
}
}
Can someone help me acquiring clear understanding on this topic? Thank you so much.
If you want to describe a function that does not return a value, you can use the Void type. This is a standard Java class, but is intended for use in this situation.
E.g.
Function<String, Void> stringPrinter = s -> {
System.out.println(s);
return null; // must return some value, null is acceptable since there is no Void instance
};
The return null; is important since, from the compiler's point of view, Void is just like any other class (e.g. String, Integer, etc). It doesn't know that it represents the absence of a value, whereas it does know that a function that returns void does not have a return value.
This means the compiler still expects some return statement in your code, just as if it were returning an Integer, and so you must return null;
EDIT:
You may find, however, if you are strictly dealing with functions with no returns, you are better suited to use a Consumer<T>. For example:
Consumer<String> stringPrinter = s -> System.out.println(s);
stringPrinter.accept("hello");
or, using a method reference:
Consumer<String> stringPrinter = System.out::println;
stringPrinter.accept("hello");
You can use Reflection API to pass a void method as a reference e.g.
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
Class[] classParams = new Class[1];
classParams[0] = String.class;
Method method = Main.class.getMethod("hello", classParams);
Main obj = new Main();
System.out.println(new Main().getSum(obj, method, "world!", 10, 20));
}
public void hello(String msg) {
System.out.println("Hello " + msg);
}
int getSum(Object object, Method method, String msg, int x, int y) throws Exception {
Object[] objectParams = new Object[1];
objectParams[0] = msg;
method.invoke(object, objectParams);
return x + y;
}
}
Output:
Hello world!
30
Callable<Boolean> callable = new Callable<Boolean>() {
public Boolean call() throws Exception {
return true; // do something useful here
}
};
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() =====>
.retryIfResult(Predicates.<Boolean>isNull()) =====>
.retryIfExceptionOfType(IOException.class)
.retryIfRuntimeException()
.withStopStrategy(StopStrategies.stopAfterAttempt(3))
.build();
try {
retryer.call(callable);
} catch (RetryException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Qustion:
RetryerBuilder.<Boolean>newBuilder() this line.
Why we can put <Boolean> before a method?
this is a strange to me in Java.
can someone explain it for me thanks
This is a so called generic method. Usually, the return type of generic method (in the example below, T test(T obj)) is determined by assignment, i.e. String foo = Foo.test("bar"). If you call a method without assigning its return value to a variable, you must resolve the generic inline.
class Foo {
public static <T> T test(T obj) {
return obj;
}
public static void main(String[] args) {
String foo = Foo.test("foo");
System.out.println(foo); // output: "foo"
System.out.println(Foo.<String>test("Test")); // output: "Test"
System.out.println(Foo.<Integer>test(16)); // output: "16"
}
}
here is the thing, in java you can write method like this:
static <T> T method(T obj) {
return obj;
}
which will mean that java will detect type T during compilation, so:
Integer r1 = method(new Integer(0));
will compile fine, but:
String r2 = method(new Integer(0));
will give you compilation error
now, imagine situation:
static <T> T test(); // implementation of such method is not important right now, usually it is some kind of "reflection magic"
static void method1(String s);
static void method1(Integer i);
when you're calling with known types, everything works fine:
String s = test();
Integer i = test();
method1("string");
method1(1);
but, what if you do like this:
method1(Foo.test());
which method will be called? java cannot decide and will give you compilation error, to resolve it you have to indicate type, like this
method1(Foo.<String>test());
So, answer to your question
Why we can put <Boolean> before a method?
We can put it to resolve ambiguity when java compiler cannot detect type.
this is a variable which holds the reference ID of the current object.
So why it cannot be used as a reference variable ?
Temp t = new Temp(); //Temp be any class
t.show(); //show() be any method in Temp
this.show(); // error
That will only throw an error if the class you're in does not have a show() method or if you are trying to do that from a static context.
this hold the reference ID of the current object so it depends where you are and not what objects you've just created.
Current object is not an object you referred last. Here is example of this usage:
public class Temp {
private int x = 3;
public void show() {
this.x = 4;
this.show(); // same as show();
}
}
The "this" keyword in java is to reference the object the code is running in.
It is mostly useful you are comparing the object within itself. Example:
public boolean equals(Object object) {
return object == this;
}
Here is another snippet of code to help you understand:
public class Test {
public Test() {
}
public static void main(String... args) {
Test test = new Test();//original test object
Test test2 = new Test();
test.equals(test);//returns true
test.equals(test2);//returns false
}
public void equals(Test testParameter) {
// in this particular case "this" refers to the
// original test object (defined in the main method)
// as it is the only object calling this method.
return testParameter == this; // "this" is the object that is calling the method
}
}
Is there any function in java that lets you jump to another method?
This is an example how it should work:
if (boolean expression(){
jump to public void something;
if (boolean expression) {
jump to public void something2;
} else{
jump to public void 3;
}
This is needed for a program that checks 3 numbers, and they have different methods linked to them.
If by jump, you mean calling a method:
if (boolean expression(){
something();
if (boolean expression(){
something2();
}
else{
something3();
}
Simply invoke it, in your example
if (boolean expression(){
something();
} else if (boolean expression(){
something2();
} else{
something3();
}
instead of jump to public void something just call something()
There is no syntax called "jump to" although you can easily call a method by firstly making a method.
public void myMethod(){
// do something
}
now when you have done this, you call it from another method by invoking it's name myMethod();. You might know that a method can either return a variable or return nothing (void) if you give it a return-type you MUST return a variable with the same type as your method.
For example:
public int oneplusone(){
int integer = 1 + 1;
return integer;
}
and a void would be like this:
public void oneplusone(){
int integer = 1 + 1;
System.out.println(integer);
}
When you've specified your method you need to call it by invoking its name from another place in your program. Final example:
public class Snippet(){
public static void main(String args[]){ // THIS IS THE MAIN METHOD OF YOUR PROGRAM!
Snippet snippet = new Snippet();
System.out.println(snippet.oneplusone());
}
public int oneplusone(){
int integer = 1 + 1;
return integer;
}
}
I suggest you should check out thenewboston java tutorials explaning java for beginners. Good luck!
if you have the mothod call in the class just call the method like
something(int i);
if your method is in another class make sure you have an object of that class if the method isn't static and call your method
Foo foo = new Foo();
foo.something(10);
The below code shows my problem. Effectively, I am trying to use Mockito's ArgumentCaptor to verify that a method was called once with a certain concrete class. I would like to use ArgumentCaptor here if possible, but I am beginning to suspect I need to use a custom ArgumentMatcher instead.
The problem is that the line Mockito.verify(mocked).receive(captor.capture()); (Edit: Added this to the code below) fails with a TooManyActualInvocations exception (2 instead of 1). I would like to understand why this is happening - is it poor implementation of Mockito or a limitation caused by type erasure of generics?
public class FooReceiver {
public void receive(Foo foo) {
}
}
public interface Foo {
}
public class A implements Foo {
}
public class B implements Foo {
}
public class TestedClass {
private FooReceiver receiver;
public TestedClass(FooReceiver receiver) {
this.receiver = receiver;
}
public void doStuff() {
receiver.receive(new A());
receiver.receive(new B());
}
}
public class MyTest {
#Test
public void testingStuff() {
// Setup
FooReceiver mocked = Mockito.mock(FooReceiver.class);
TestedClass t = new TestedClass(mocked);
// Method under test
t.doStuff();
// Verify
ArgumentCaptor<B> captor = ArgumentCaptor.forClass(B.class);
Mockito.verify(mocked).receive(captor.capture()); // Fails here
Assert.assertTrue("What happened?", captor.getValue() instanceof B);
}
}
EDIT:
For anyone interested, I ended up doing this:
// Verify
final B[] b = new B[1];
ArgumentMatcher<B> filter = new ArgumentMatcher<B>() {
#Override
public boolean matches(Object argument) {
if(argument instanceof B) {
b[0] = (B) argument;
return true;
}
return false;
}
}
Mockito.verify(mocked).receive(Mockito.argThat(filter));
As far as I can tell this is a limitation / poor implementation.
When looking at org.mockito.internal.matchers.CapturingMatcher there is
public boolean matches(Object argument) {
return true;
}
meaning it matches every argument / class.
This results in org.mockito.internal.matchers.CapturingMatcher#getAllValues returning a List<B> but actually containing one A and one B resulting in a ClassCastException during runtime when trying to get them as B.
List<Object> arguments; // the invocations
// adds a new invocation
public void captureFrom(Object argument) {
// ...
this.arguments.add(argument);
// ...
}
// return the list of arguments, using raw types remove any compiler checks for validity,
// the returned List contains elements that are not of type T
public List<T> getAllValues() {
// ...
return new ArrayList<T>((List) arguments);
// ...
}
This should be solvable by changing org.mockito.ArgumentCaptor in a way that it passes its Class<? extends T> clazz into the CapturingMatcher and therefore passing the type information along properly, enabling a proper matches implementation and removing the need for the cast / raw type usage.
You can also use Mockito.isA to verify that the argument is of a specific class:
verify(mock).init(isA(ExpectedClass.class));
Mockito JavaDoc
The method will be called twice so you need to do this:
Mockito.verify(mocked, times(2)).receive(captor.capture());