class A {
final int finalValue;
public A( B b ) {
super();
b.doSomething( this ); // this escapes!
finalValue = 23;
}
int getTheValue() {
return finalValue;
}
}
class B {
void doSomething( A a ) {
System.out.println( a.getTheValue() );
}
}
Why is it printing zero? Instead of 23?
I have found this example on Wikipedia site
Update:
My question was very bad and i totally missed the point...
They say that pointer this goes out of scope and object wont be created fully
I wanted to ask if someone more experienced can explain that to me because im new in world of programing
In your IDE set a breakpoint in the getTheValue() method and observe the stack at that point. You are calling constructor->doSomething->getTheValue before an assignment has been done. At that point it is still 0, the guarantee is that it assigned during the construction phase and not modified after, which is still true.
Modify your code like this to fix the issue:
public A( B b ) {
super();
finalValue = 23;
b.doSomething( this ); // this escapes!
}
Related
I'm just new to Java OOP, and I hardly understand about the class and stuff. I tried to write some code to understand but I didn't succeed. Here is my code, I expected it to return the number of eggs but I don't know why it returns nothing.
class EggCounter {
private int egg;
{
egg = 0;
}
public void eggAdd()
{
egg = egg + 1;
}
public void eggBreak()
{
egg = egg - 1;
}
public void eggAddDozen()
{
egg = egg + 12;
}
public int getEgg()
{
return egg;
}
}
public class EggTest
{
public static void main(String[]args)
{
EggCounter egg = new EggCounter();
egg.eggAdd();
egg.eggAddDozen();
egg.eggBreak();
egg.getEgg();
}
}
It does return 12. Replace the egg.getEgg(); line in your main method with System.out.println(egg.getEgg()); and you will notice it prints 12.
It is returning, it's just that you do nothing with the return value of getEgg. What you need to do is store it into the variable or do something with it. return <value> only returns the given value to the callee, you must store it to use it. Example:
int eggCount = egg.getEgg();
System.out.println(eggCount);
Here, the assignment of eggCount calls egg.getEgg(). The call resolves when the number of eggs is returned, which assigns the return value to eggCount. Finally, it will print out eggCount. If you need the result of egg.getEgg() later, you can simply just output the following:
System.out.println(egg.getEgg());
How this works is the method egg.getEgg() is called. The return value is then resolved, which is passed into the print statement. This gets rid of storing it into a variable you can use later.
I have read the similar question and learnt that it is not possible to use a ternary operation instead of if statement, which does not have else statement. Because, if-without else statements are binary not ternary. My question is more best-practice.
In my code, there are lots of code snippet like that
if( calculation < 1 ){
calculation= 0;
}
I would like to shorten these with tenary. Is it a good practice to change these statements with the following.
calculation = calculation < 1 ? 0 : calculation;
You could create a class (or classes) that would create a nice fluent API. Such that your line would be:
calculationTo = replace(calculationTo).with(0).when(calculationTo < 1)
In my opinion it doesn't read much better than a standard if statement, but it also depends on the conditions that you have.
Example implementation:
public class Replacer<T> {
private final T value;
private T replacementValue;
private Replacer(T value) {
this.value = value;
}
public static <V> Replacer<V> replace(V value) {
return new Replacer<V>(value);
}
public Replacer<T> with (T replacementValue) {
this.replacementValue = replacementValue;
return this;
}
public T when(boolean condition) {
if (condition) {
return replacementValue;
} else {
return value;
}
}
}
import static somepackage.Replacer.replace;
public class Main {
public static void main(String[] args) {
int calculationTo = 3;
calculationTo = replace(calculationTo).with(0).when(calculationTo < 1);
}
}
You might expand it or make condition a function so it can be used with lambda, etc. I would also make method with return object of different class (e.g. ReplacerWithValue) so that calling with twice in one chain would result in compilation error.
Since you're asking for a best practice, I'll point out something where you could do better and then I'll tell you why I like the ternary operator.
Let me rephrase you're code snippet:
if (calculatedValueAfterStep1 < 1) {
calculatedValueAfterStep2 = 0;
} else {
calculatedValueAfterStep2 = calculatedValueAfterStep1;
}
When you read your code and somebody asks you "what does 'calculation' represent?" then you cannot answer this question without asking for the line number. The meaning of "calculation" changes over the course of the program code. If you cannot explain what a variable means, you cannot give it a good name. This is why I like my Version better. There is a clear Definition of what meaning the variables "calculatedValueAfterStep1" and "calculatedValueAfterStep2" are. Yes, the names are bad. Change them to your domain accordingly.
Now when you look at the code, you'll notice that "calculatedValueAfterStep2" is not declared. So let's Change the code:
int calculatedValueAfterStep2 = -1;
if (calculatedValueAfterStep1 < 1) {
calculatedValueAfterStep2 = 0;
} else {
calculatedValueAfterStep2 = calculatedValueAfterStep1;
}
Now it gets ugly. The same person asking the earlier question will now ask "why is 'calculatedValueAfterStep2' initialized with '-1'?". So here comes the ternary operator:
int calculatedValueAfterStep2 = (calculatedValueAfterStep1 < 1) ? 0 : calculatedValueAfterStep2;
beautiful!
public static int someFunc(int a, int b){
while(a <=b){
a+= 1;
return a;
}
return b;
}
so i was expecting it to return the new value over and over but it didnt, once i executed the code and saw for myself that, i realised it had something to do with pass by value or by reference which is something i dont really understand! can someone explain?
The immediate problem is that return returns! Nothing after it can be executed. You can't have a meaningful loop with an unconditional return in it.
As far as the other, no. That's not the issue as you return the new value of a. The a you passed in remains unchanged which is the pass by reference/value you speak of. Java is pass by value.
public class JHelp {
public static void main(String...args) {
JHelp j = new JHelp();
int a = 1;
System.out.print(j.f(a));
System.out.print(a);
}
int f(int a ) {
a += 1;
return a;
}
}
Will give you an output of:
21
because the return instruction exits the code hence the methods done its job it doenst need to iterate again once it reaches the return instruction, i however would have done it if the return instruction wasnt reached.
I have code of the following form:
class Test {
private final A t;
public Test() {
for ( ... : ... ) {
final A u = null;
}
t = new A();
}
private class A {}
}
Compiler says:
variable t might already have been assigned
Interestingly, if I perform any of the following changes to the loop it works out!
Change the loop's content to A u = null
Remove the loop (but keep final A u = null;)
Replace the foreach-style loop with a classic counting loop
What is going on here?
Note: I could not get the minimal example to cause the error so there is probably something wrong with the "environment" (about 1400 loc). I can not see what could disturb the initialisation of t, though, as t is written to nowhere else.
Fun fact: IntelliJ IDEA says "Variable 'u' can have 'final' modifier..." if I remove it.
I use javac 1.6.0_26.
Update: There you go, this example so so minimal:
import java.util.List;
class A {
private final boolean a;
public A() {
for ( final Object o : new Object[] {} ) {
final Object sh = null;
}
a = true;
}
class B {
private final Object b1;
private final Object b2;
B() {
b1 = null;
b2 = null;
}
}
}
Fails to compile on javac 1.6.0_26 but compiles on javac 1.7.0_02. So I guess I hit some wicked corner case of ... something?
Note that you can do any of
Remove any one member
Remove final inside the loop in A()
Replace the loop with a normal for loop, e.g. for ( int i=0; i<100; i++ ) { ... }
and it will compile.
If you have lots of code I would try this.
private final A t;
public Test() {
final int t = 1;
for ( ... ) {
final A u = null;
}
this.t = new A();
This will cause any code which "might" initialise t to fail (and show up in the compiler.
If you're constructor happen to call another constructor that doesn't itself set t, the compiler fails to understand that.
See here.
As the problem is fixed in Java 7, it is probably a bug in the Java 6 compiler.
It is my understanding that storing an object in a final var does not make your object immutable but its reference. That explain why when you remove the final keyword it works and as per removing the for-loop, i think you are accessing the object reference and not an instance.
I'd like to call a method that either returns false, or an integer. At the moment my code is:
int winningID = -1;
if((ID = isThereAWinner()) != -1) {
// use the winner's ID
} else {
// there's no winner, do something else
}
private int isThereAWinner() {
// if a winner is found
return winnersID;
// else
return -1;
}
I don't like the if((ID = isThereAWinner()) != -1) bit as it doesn't read very well, but unlike C you can't represent booleans as integers in Java. Is there a better way to do this?
I would use something similar to Mat's answer:
class Result {
public static Result withWinner(int winner) {
return new Result(winner);
}
public static Result withoutWinner() {
return new Result(NO_WINNER);
}
private static final int NO_WINNER = -1;
private int winnerId;
private Result(int id) {
winnerId = id;
}
private int getWinnerId() {
return winnerId;
}
private boolean hasWinner() {
return winnerId != NO_WINNER;
}
}
This class hides the implementation details of how you actually represent if there were no winner at all.
Then in your winner finding method:
private Result isThereAWinner() {
// if a winner is found
return Result.withWinner(winnersID);
// else
return Result.withoutWinner();
}
And in your calling method:
Result result = isThereAWinner();
if(result.hasWinner()) {
int id = result.getWinnerId();
} else {
// do something else
}
It may seem a little bit too complex, but this approach is more flexible if there would be other result options in the future.
What about something like:
private int getWinnerId() {
// return winner id or -1
}
private boolean isValidId(int id) {
return id != -1; // or whatever
}
int winnerId = getWinnerId();
if (isValidId(winnerId)) {
...
} else {
...
}
This is all quite subjective of course, but you usually expect an isFoo method to provide only a yes/no "answer".
The problem is you are trying to return two values at once. The approach you have taken is the simplest for this. If you want a more OO or design pattern approach I would use a listener pattern.
interface WinnerListener {
void onWinner(Int winnerId);
void noWinner();
}
checkWinner(new WinnerListener() {
// handle either action
});
private void checkWinner(WinnerListener wl) {
// if a winner is found
wl.onWinner(winnersID);
// else
wl.noWinner();
}
This approach works well with complex events like multiple arguments and multiple varied events. e.g. You could have multiple winners, or other types of events.
I'm afraid not. To avoid errors caused by mistaking if(a == b) for if(a = b), Java removes the conversion between boolean type and number types. Maybe you can try exceptions instead, but I think exception is somewhat more troublesome. (My English is not quite good. I wonder if I've made it clear...)
Perhaps you may wish to consider exceptions to help you with your understanding of asthetics of coding.
Use Integer instead of int and return null instead of -1. Look from this point: "I am returning not integer, but some object that represents winner identity. No winner - no instance"
Joe another suggestion, this is constructed based on #Mat and #buc mentioned little while ago, again this is all subjective of course I'm not sure what the rest of your class/logic is. You could introduce an enum with different ResultStatuses if it makes sense within the context of your code/exmaple.
As Matt mentioned you would expect isValid method to return a boolean yes/no (some may also complain of readability)
public enum ResultStatus {
WINNER, OTHER, UNLUCKY
}
This could be an overkill as well and depends on the rest of your logic (and if logic is expanding) but I thought I'll suggest nonetheless my two cents! So therefore in your public class (similar to #bloc suggested) you could have a method such as below that will return the status of the result checked.
public ResultStatus getResultStatus() {
if (isWinner()) {
return ResultStatus.WINNER;
} else {
return isOtherCheck() ? ResultStatus.OTHER : ResultStatus.UNLUCKY;
}
}