How to block attributes from being used in java - java

Basically I would like to know if there is a way to "disable" an attribute within a block after a certain point.
For example check the following scenario:
for(int i=0;i<10;i++){
for(int j=i+5;j<50;j++){
//from here until end of the block I want to make sure I don't use **i** anymore.
print(j*5+i); //I want this line to produce compiler error
}
}
Don't get me wrong I understand it is a bad programming, but I still can't help but to use i,j,k,h as attributes. and sometimes I make a mistake by misplacing the attributes in wrong places.

Call a method.
for (int i = 0; i < 10; i++) {
for (int j = i + 5; j < 50; j++) {
doSomething();
}
}
...
private void doSomething() {
// Woot, no i and no j!
}

Your code doesn't make sense to anybody. You need to divide it into functions with good names so that anyone can understand what your program is doing without comments around the code or getting mixed up with variables.
Here's an example for the code you have posted:
public void printNumberTimes5(int number) {
print(number*5);
}
But don't stop there, make it obvious what the loop is doing too:
public void printSomeNumbers(int someNumber) {
for(int j=someNumber+5;j<50;j++){
printNumberTimes5(j);
}
}
And again:
public void printSomeNumbers_repeat(int repeat) {
for(int i=0;i<repeat;i++){
printSomeNumbers(i);
}
}
I don't really know what you're doing but renaming the function to what you're supposed to be doing would make it clear.
Remember: each function should only have one job.
Finally, give i and j real names so that you understand what those numbers do and don't mix them up.

The best way to obtain this in java, is by using scope. Make sure that the variables are in different scopes and then you don't have access to it. A good guideline to follow is to split your logic in various small methods, this way you'll ensure the desired behavior.

My recommendations in order of preference:
Use meaningful variable-names. Maybe i isn't as good as e.g. row, ...
Use functions to group operations and also reduce the variables they can access. This can also lead to a point where repeating operations can easily be reused.
Use a custom counter-object like this one
/**
* Created for http://stackoverflow.com/q/25423743/1266906
*/
public class ObliviousLoops {
public static void main(String[] args) {
for(LockableCounter i = new LockableCounter(0); i.getValue() < 42; i.unlock().increment()) {
System.out.println("A-loop:" + i.getValue());
i.lock();
// No access, everything is fine
}
for(LockableCounter i = new LockableCounter(0); i.getValue() < 42; i.unlock().increment()) {
System.out.println("B-loop1:" + i.getValue());
i.lock();
// Next statement will throw an Exception
System.out.println("B-loop2:" + i.getValue());
}
}
static class LockableCounter {
private long value;
private boolean locked;
LockableCounter(long value) {
this.value = value;
}
public LockableCounter lock() {
this.locked = true;
return this;
}
public LockableCounter unlock() {
this.locked = false;
return this;
}
public long getValue() {
if(locked) {
throw new IllegalStateException("Accessing locked counter");
}
return value;
}
public void increment() {
if(locked) {
throw new IllegalStateException("Accessing locked counter");
}
value++;
}
#Override
public String toString() {
if(locked) {
throw new IllegalStateException("Accessing locked counter");
}
return String.valueOf(value);
}
}
}
the most obvious draw-backs of the last solution is a less fluent handling of the value, less ways to optimize the operations for the compiler, ... in practice you may even want to replace the LockableCounter by something different, once you are sure you calculations are written as desired to speed things up.
Use Java 8's lambda-function to build something behaving similar to for-loops where you can null-out the counter for the rest of the cycle (actually this is a variant of #2)
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* Created for http://stackoverflow.com/q/25423743/1266906
*/
public class LambdaLoops {
public static void main(String[] args) {
iterate(0, 42, (i) -> {
System.out.println("A-loop:" + (i + 0));
i = null;
});
iterate(0, (i) -> i < 42, (i) -> ++i, (i) -> {
System.out.println("B-loop:" + (i + 0));
i = null;
});
iterate(0, (i) -> i < 42, (i) -> {
System.out.println("C-loop1:" + (i + 0));
i = null;
// Next statement will not throw an Exception
System.out.println("C-loop2:" + i);
// Next statement will throw an Exception
System.out.println("C-loop3:" + (i + 0));
});
}
static void iterate(Integer initial, Integer limit, Consumer<? super Integer> function) {
for (Integer i = initial; i < limit; i++) {
function.accept(i);
}
}
static void iterate(Integer initial, Predicate<? super Integer> when, Consumer<? super Integer> function) {
for (Integer i = initial; when.test(i); i++) {
function.accept(i);
}
}
static <T> void iterate(T initial, Predicate<? super T> when, Function<? super T, ? extends T> increment, Consumer<? super T> function) {
for (T i = initial; when.test(i); i = increment.apply(i)) {
function.accept(i);
}
}
}
as in #3 this will most likely lead to decreased performance, but has the advantage, that your IDE might alert you, that i will always be null. This should however be easier to optimize be inlining than #3 as there is no additional boolean involved. If and when the JIT does inlining is however hard to guess.

Since so many of answers talk about why this is a bad idea, so I won't repeat it.
One solution that comes to my mind is to use an counter object. Whenever you want a particular counter to go out of scope, set that to null. If you use it after this point, a Null pointer access warning is shown (at least in eclipse. I suspect other IDEs should also have this feature. Not sure whether javac generates a warning).
public class DisappearingVariables {
public static class Counter {
int i = 0;
public Counter() {
}
public void inc() {
i++;
}
public int get() {
return i;
}
}
public static void main(String[] args) {
for(Counter i = new Counter(), oi = i; i.get() < 10; i = oi, i.inc()) {
System.out.println("i = " + i.get());
i = null;
i.inc(); // This line gets a warning
for(int j = 0; j < 10; j++) {
}
}
}
}

Related

Addition of two generics in Java (cast not working)

I am currently learning about generics in Java, coming from C++ it's quite a difference.
I'd like to a vector addition, in C++, it would look something like this. (I know that this code is not well-written, it's just for a quick example to show what I want to do)
#include <iostream>
#include <vector>
template <typename T>
class Vect{
public:
std::vector<T> vect;
Vect(std::vector<T> t){vect = t;}
T index(int i){return vect[i];}
void print(){
for(int i = 0; i < vect.size(); ++i){
std::cout << vect[i] << " ";
}
std::cout << std::endl;
}
void add(Vect<T> other){
for(int i = 0; i < vect.size(); ++i){
vect[i] = vect[i]+other.index(i);
}
}
};
int main(){
std::vector<int> p1;
p1.push_back(1);
p1.push_back(2);
p1.push_back(3);
p1.push_back(4);
Vect<int> vec1 = Vect<int>(p1);;
Vect<int> vec2 = Vect<int>(p1);;
vec1.print();
vec2.print();
vec1.add(vec2);
vec1.print();
return 0;
}
I am trying to do the same with Java but I can't get a way to add two generics T and put the value (a T) in the first vector. I am doing this :
public class Vect0<T extends Number> {
//Attributs
private T[] _vec;
//Constructeur
public Vect0(T[] vec){
System.out.println("Construction du _vec !");
_vec = vec;
}
//Getter
public int get_length() {
return _vec.length;
}
//Methodes
public void print(){
System.out.print("[");
for (int i = 0; i < _vec.length; ++i){
if (i != _vec.length-1) {
System.out.print(_vec[i] + ", ");
}
else {
System.out.print(_vec[i]);
}
}
System.out.println("]");
}
public T index(int i) {
return _vec[i];
}
public void sum(Vect0<T> other) {
if (other.get_length() == this.get_length()) {
for(int i = 0; i < this.get_length(); ++i) {
Double res = (this.index(i).doubleValue() + other.index(i).doubleValue());
System.out.print(res);
T t = (T) res;
_vec[i] = t;
}
}
}
}
So it does print a double, but then the casting doesn't work and I get an error :
Exception in thread "main" java.lang.ArrayStoreException:
java.lang.Double at Vect0.sum(Vect0.java:37) at
Main.main(Main.java:12)
I hope you can help me figure this out.
Thank you very much.
Take a look at the code below. The explanation of your problem is in the comments.
public class TestGenerics {
public static void main(String[] args) {
Integer[] ints = new Integer[] { 1 };
Double[] doubles = new Double[] { 1.0 };
// By not telling the compiler which types you're
// expecting it will not be able to deduce if
// the usage of the generic methods are going
// to be ok or not, because the generics notation is
// erased and is not available at runtime.
// The only thing you will receive by doing this
// is a warning telling you that:
// "Vect0 is a raw type.
// References to generic type Vect0<T> should be parameterized"
Vect0 rawVect0 = new Vect0(ints);
Vect0 rawVect1 = new Vect0(doubles);
// This will throw java.lang.ArrayStoreException
// because you're trying, at runtime, to cast
// a Double object to Integer inside your sum method
// The compiler doesn't have a clue about that so it
// will blow at runtime when you try to use it.
// If you're only working with Integers, than you should not
// cast the result to double and should always work with intValues
rawVect0.sum(rawVect1);
// In Java, when using generics, you should be
// explict about your types using the diamond operator
Vect0<Integer> vect2 = new Vect0<>(ints);
Vect0<Double> vect3 = new Vect0<>(doubles);
// Now that you told the compiler what your types are
// you will receive a compile time error:
// "The method sum(Vect0<Integer>) in the type Vect0<Integer>
// is not applicable for the arguments (Vect0<Double>)"
vect2.sum(vect3);
}
}
If you read about the ArrayStoreException it will become clearer:
public class ArrayStoreException extends RuntimeException Thrown to
indicate that an attempt has been made to store the wrong type of
object into an array of objects. For example, the following code
generates an ArrayStoreException:
Object x[] = new String[3];
x[0] = new Integer(0);
Whenever dealing with Generic methods you should think that the Producer should use extends and the Consumer should use super - PECS. This is a good thing to know. Check out this question:
What is PECS (Producer Extends Consumer Super)?
One solution to your case, if you really want to be able to add different types of Number, is to always work inside the Vect0 object with one specific type (Double). Check out the code below:
public class Vect0<T extends Number> {
// Attributs
private Double[] _vec;
// Constructeur
public Vect0(T[] vec) {
System.out.println("Construction du _vec !");
if (vec instanceof Double[]) {
_vec = (Double[]) Arrays.copyOf(vec, vec.length);
} else {
_vec = Arrays.stream(vec).map(Number::doubleValue).toArray(Double[]::new);
}
}
// Getter
public int get_length() {
return _vec.length;
}
// Methodes
public void print() {
System.out.print("[");
for (int i = 0; i < _vec.length; ++i) {
if (i != _vec.length - 1) {
System.out.print(_vec[i] + ", ");
} else {
System.out.print(_vec[i]);
}
}
System.out.println("]");
}
public Double index(int i) {
return _vec[i];
}
public void sum(Vect0<T> other) {
if (other.get_length() == this.get_length()) {
for (int i = 0; i < this.get_length(); ++i) {
// Now you're only working with Doubles despite of the other object's true type
_vec[i] = index(i) + other.index(i);
}
}
}
}
And in order to use it, you should reference the objects using the super class Number, like this:
Vect0<Number> vect2 = new Vect0<>(ints1);
Vect0<Number> vect3 = new Vect0<>(doubles1);
// now it will be able to add two different types without complaining
vect2.sum(vect3);
If you want something more elaborate, you could start by checking out this question: How to add two java.lang.Numbers?
Cheers!
References:
Erasure of Generic Methods
ArrayStoreException
More on PECS

How can I pass code into a method without it running first?

Please help as how can I achieve below in java.
public class TestUserFunctions {
public static boolean equals(int val1, int val2){
if(val1==val2){
return true;
} else{
return false;
}
}
public static Object iterateValue(String ittr, int iterations){
for(int i=1; i <= iterations; i++){
System.out.println("Printing iteration #"+i);
}
return ittr;
}
private static void ifElse(boolean condition, Object returnstr, Object elsestr){
if(condition){
System.out.println("TRUE");
//Need a code here which will iterate string value only once.
} else{
System.out.println("FALSE");
//Need a code here which will iterate string value thrice as specified.
}
}
public static void main(String[] args){
ifElse(equals(1, 1), iterateValue("Value", 1), iterateValue("Value", 3));
}
}
I may be wrong in many aspect here with my above code. I am sorry for that.
The expected output here is
TRUE
Printing iteration #1
In case of ifElse(equals(1, 1), iterateValue("Value", 1), iterateValue("Value", 3)); the expected output is
FALSE
Printing iteration #1
Printing iteration #2
Printing iteration #3
The point is:
ifElse(equals(1, 1), iterateValue("Value", 1), iterateValue("Value", 3));
In Java, all method arguments get evaluated (aka computed) before the invocation takes place.
In other words:
equals(1,1) will always result in true
thus always the first "Value" is returned (although that doesn't really matter; as you are using the same value in both cases)
as said, both calls to iterateValue() will be executed; that means that this method is invoked twice, with the respective arguments for each call.
So, if you want to call iterateValue() only once; you should not use it as parameter. Instead, go for something like:
ifElse(equals(1,1), "ValueA", "ValueB"));
and then call iterateValue() on the first or second incoming String argument directly; and only once.
You need to defer execution of the if and else block using Java 8 lambda expressions to obtain what you want to achieve
import java.util.function.Supplier;
public class TestUserFunctions {
public static Supplier<Boolean> equals(int val1, int val2){
if(val1==val2){
return () -> true;
} else{
return () -> false;
}
}
public static Supplier<String> iterateValue(String ittr, int iterations){
return () -> {
for(int i=1; i <= iterations; i++){
System.out.println("Printing iteration #"+i);
}
return ittr;
};
}
private static void ifElse(Supplier<Boolean> condition, Supplier<String> returnstr, Supplier<String> elsestr){
if(condition.get()){
System.out.println("TRUE");
returnstr.get();
} else{
System.out.println("FALSE");
elsestr.get();
}
}
public static void main(String[] args){
ifElse(equals(1, 1), iterateValue("Value", 1), iterateValue("Value", 3));
}
}
Using Java < 8 the readability is greatly decreased
interface Supplier<T> {
public T get();
}
public class TestUserFunctions {
public static Supplier<Boolean> equals(int val1, int val2){
if(val1==val2){
return new Supplier<Boolean>() {
public Boolean get() { return true; }
};
} else{
return new Supplier<Boolean>() {
public Boolean get() { return false; }
};
}
}
public static Supplier<String> iterateValue(String ittr, int iterations){
return new Supplier<String>() {
public String get() {
for(int i=1; i <= iterations; i++){
System.out.println("Printing iteration #"+i);
}
return ittr;
};
};
}
private static void ifElse(Supplier<Boolean> condition, Supplier<String> returnstr, Supplier<String> elsestr){
if(condition.get()){
System.out.println("TRUE");
returnstr.get();
} else{
System.out.println("FALSE");
elsestr.get();
}
}
public static void main(String[] args){
ifElse(equals(1, 2), iterateValue("Value", 1), iterateValue("Value", 3));
}
}
Your problem can be expressed more succinctly like this:
public class Demo() {
static int x = 0;
static int incrementAndReturnX() {
x++;
return x;
}
static void ifElse(boolean predicate, int t, int f) {
if(predicate) {
return t;
} else {
return f;
}
}
static void main(String... args) {
System.out.println(ifElse(false, incrementAndReturnX(), incrementAndReturnX());
}
}
This prints 2.. Why is this, and how can we make it return 1?
The answer is the order in which Java calls methods. When it deals with ifElse(true, incrementAndReturnX(), incrementAndReturnX()), it runs the methods passed as parameters, so as to get an object or a primitive. Then it invokes ifElse().
So:
Java notes that true is a primitive. Nothing to do. Move on.
Java calls incrementAndReturnX(). x is incremented. 1 is returned.
Java calls incrementAndReturnX() again. x is incremented. 2 is returned.
Java uses the values it has collected to call ifElse(false, 1, 2)
You can see that the result of this is 2.
What we need is some way of passing a method to the ifElse() routine, as if it was an object, so that it can choose whether to run it or not. In Java 7, the only way we could do that was by creating classes containing our methods, so we could pass them around.
interface IntegerSupplier() {
int get();
}
...
final int[] x = new int[1];
IntegerSupplier incrementAndReturnX = new IntegerSupplier() {
x[0] += 1;
return x[0];
};
Note this is using anonymous class syntax. We are creating a new class here, and creating an instance of it, without giving it a name.
We are also wrapping x in an array, because the inner class can only refer to final variables, and we need to be able to modify the value.
public int ifOrElse(boolean predicate, IntegerSupplier t, IntegerSupplier f) {
if(true) {
return t.get();
} else {
return f.get();
}
}
The key here is that the code that increments x is in a method that's not called until inside the if block.
As of Java 8, we have a much neater way of doing the same thing. We can very succinctly declare something very like our IntegerSupplier using what is called a lambda:
Supplier<Integer> incrementAndReturnX = () {
x[0]++;
return x;
}
public int ifOrElse(boolean predicate, Supplier<Integer> t, Supplier<Integer> f) {
if(true) {
return t.get();
} else {
return f.get();
}
}
(java.util.function.Supplier is provided by the JRE: we don't need to declare our own)
This whole way of thinking is called functional programming, and is very powerful and expressive.

Is there a way to have shortcut for text in Java?

I am trying to avoid repeating masses of code and was wondering if there was a short cut for it? I want a literal shortcut, which just replaces the shortcut with text in compilation.
for example:
private int a = 0;
/*Shortcut sc = new Shortcut ( for(a = 0; a < 5; a++) ); */
if (truth = true)
sc.doTask(a);
else
sc.doTask((a+1);
I know it doesn't affect the efficiency of coding, but makes the task look a bit more organized.
It seems what you are trying to do is will leave your code unmaintainable and hard to read (Unless you were asking how to organize your code in functions).
It's not always about coding efficiency. You have to make sure that your code is not harder to maintain and understand by other developers.
If you want to avoid repetition of code put the repeated code in some well defined methods.
public class Test {
public static void main(String[] args) {
Test test = new Test();
// Now you can use the so called shortcut that is called a method everywhere you want.
int sum = test.getSum(1, 2, 3);
System.out.println("Sum is " + sum);
// Now again reuse the method instead of loads of code :)
sum = test.getSum(2, 4, 5);
System.out.println("New sum is " + sum);
}
public int getSum(int... numbers) {
int sum = 0;
for (int num : numbers) {
sum += num;
}
return sum;
}
}
BTW. Your if(truth=true) is assignment to variable called "truth" and will always evaluate to true. Your else will never be called.
Ill take a stab. To reduce boiler plate code you can use methods. Take this example
public class MyFooClass {
private int[] numbers;
public void doStuff1() {
// do something
for(int i=0;i<numbers.length;i++) {
// check for duplicates or something
}
}
public void doOtherStuff() {
// do something
for(int i=0;i<numbers.length;i++) {
// check for duplicates or something
}
}
}
as you can see we check for duplicates 2 times, we can reuse that code in another method.
public class MyFooClass {
private int[] numbers;
public void doStuff1() {
// do something
checkForDuplicatesOrSomething();
}
public void doOtherStuff() {
// do something
checkForDuplicatesOrSomething();
}
private void checkForDuplicatesOrSomething() {
for(int i=0;i<numbers.length;i++) {
// check for duplicates or something
}
}
}
Instead of calling System.out.println("blah blah blah my text"); each time you want to print something you could code your own method like this.
public void p(Object o) {
System.out.println(o);
}
Then in your code simply call this method like this:
String s = "foo";
StringBuilder sb1 = new StringBuilder("i hate this town");
p(s);
p(sb1);

Check for infinite calls/recusrive calls algorithm

This is a subset of the problem I am trying to tackle. Assume that I have parsed some code and now I am trying to check if it is logically correct. One of those checks is that functions calls can't call themselves or be involved in another function calling each other or a function of a function calling each other, and so on.
I have tackled the problem and was able to easily solve the call to itself and one level down though it might not be the optimal code. Right now, performance is not an issue.
Here is the logic I have coded along with an example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LoopTest {
public static void main(String[] args) {
List<Loop> test = new ArrayList<Loop>();
test.add(new Loop("Function1",new String[]{"Function2", "Function1"}));
test.add(new Loop("Function2",new String[]{"Function3", "Function1"}));
test.add(new Loop("Function3",new String[]{"Function1"}));
checkLooping(test);
}
public static void checkLooping(List<Loop> input) {
for(Loop main : input) {
for(int i = 0; i < main.getInputSize(); i++) {
if(main.getName().equals(main.getInputValue(i))) {
System.err.println("Looping condition found at " + main.getName());
}
for(Loop inside : input) {
for(int j = 0; j < inside.getInputSize(); j++) {
if(main.getInputValue(i).contains(inside.getName()) &&
main.getName().equals(inside.getInputValue(j))) {
System.err.println("Looping condition found between "
+ main.getName() + " and " + inside.getName());
}
}
}
}
}
}
}
class Loop {
private String name;
private String input[];
public Loop(String name, String input[]) {
this.name = name;
this.input = input;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getInput() {
return input;
}
public void setInput(String[] input) {
this.input = input;
}
public int getInputSize() {
return input.length;
}
public String getInputValue(int i) {
return input[i];
}
public boolean contains(String search) {
if(name.contains(search))
return true;
else
return false;
}
#Override
public String toString() {
return String.format("%s %s", this.name, Arrays.toString(input));
}
}
This won't catch that Function1 exists in Function3. So if it is deeper than level 1, it won't catch it based on my logic. Is there another way to do so?
Thanks in advance!
Is there another way to do so?
Yes it is a graph traversal problem; specifically the problem of detecting circular references in (in this case) the graph of method calls.
A simple algorithm goes like this:
def detect_cycle(node, seen={}):
if seen contains node:
// found a cycle
seen.add(node)
foreach child in node.children:
detect_cycle(child, seen)
(You don't need an explicit graph structure to do this traversal. The same approach can be used to traverse/check a graph that is implied by another data structure.)
However, what we are actually doing here is checking for recursive calls. We won't be able to distinguish between recursion that terminates (which is ok) and infinite recursion (which is bad). And THAT is a really difficult problem. (In fact, computation theory says that the most general form of the problem of proving termination has no solution.)
As a matter or interest ( :-) ) the graph traversal algorithm above is an example of a program with good recursion. However, it would be a huge amount of work to write a program that can prove that it will terminate ... and identify the theoretical case where it won't!
Thanks to #StephenC
Here is my running code after I converted to using Map:
private static Map<String, List<String>> main;
// more code from above
public void detectCycle(String node, Stack<String> seen) {
if(seen.contains(node)) {
System.out.println("found cycle at " + node + " and " + seen.get(seen.size()-1));
return;
}
else
seen.push(node);
if(main.get(node) != null && main.get(node).size() != 0) {
for(int i = 0; i < main.get(node).size(); i++) {
detectCycle(main.get(node).get(i), seen);
}
}
if(!seen.isEmpty())
seen.pop();
return;
}

How to simulate constructor race conditions?

I am reading "Java Concurrency in practice" and looking at the example code on page 51.
This states that if a thread has references to a shared object then other threads may be able to access that object before the constructor has finished executing.
I have tried to put this into practice and so I wrote this code thinking that if I ran it enough times a RuntimeException("World is f*cked") would occur. But it isn't doing.
Is this a case of the Java spec not guaranting something but my particular implementation of java guaranteeing it for me? (java version: 1.5.0 on Ubuntu) Or have I misread something in the book?
Code: (I expect an exception but it is never thrown)
public class Threads {
private Widgit w;
public static void main(String[] s) throws Exception {
while(true){
Threads t = new Threads();
t.runThreads();
}
}
private void runThreads() throws Exception{
new Checker().start();
w = new Widgit((int)(Math.random() * 100) + 1);
}
private class Checker extends Thread{
private static final int LOOP_TIMES = 1000;
public void run() {
int count = 0;
for(int i = 0; i < LOOP_TIMES; i++){
try {
w.checkMe();
count++;
} catch(NullPointerException npe){
//ignore
}
}
System.out.println("checked: "+count+" times out of "+LOOP_TIMES);
}
}
private static class Widgit{
private int n;
private int n2;
Widgit(int n) throws InterruptedException{
this.n = n;
Thread.sleep(2);
this.n2 = n;
}
void checkMe(){
if (n != n2) {
throw new RuntimeException("World is f*cked");
}
}
}
}
You don't publish the reference until after the constructor has finished, change Widgit like this:
private class Widgit{ // NOTE: Not class is not static anymore
private int n;
private int n2;
Widgit(int n) throws InterruptedException{
this.n = n;
w = this; // publish reference
Thread.sleep(2);
this.n2 = n;
}
void checkMe(){
if (n != n2) {
throw new RuntimeException("World is f*cked");
}
}
Should now throw.
Edit: You should also declare the Widgit field as volatile:
private volatile Widgit w;
Well, you need to understand the issues a little more. It isn't really a case of anything being or not being "guaranteed." With concurrency problems, nothing is really guaranteed unless you really do specific things to force the problem to happen. You're just relying on the hope that enough runs should produce, which is not the case. These kinds of problems are hard to predict, which is why concurrency is a hard problem. You could try doing more work in your functions, but I assure you these are real problems that the runtime is not going to save you from.
Before sleeping, start a new thread which prints the value of n2. You will see the second thread can access the object before the constructor has finished.
The following example demonstrates this on the Sun JVM.
/* The following prints
Incomplete initialisation of A{n=1, n2=0}
After initialisation A{n=1, n2=2}
*/
public class A {
final int n;
final int n2;
public A() throws InterruptedException {
n = 1;
new Thread(new Runnable() {
public void run() {
System.out.println("Incomplete initialisation of " + A.this);
}
}).start();
Thread.sleep(200);
this.n2 = 2;
}
#Override
public String toString() {
return "A{" + "n=" + n + ", n2=" + n2 + '}';
}
public static void main(String... args) throws InterruptedException {
System.out.println("After initialisation " + new A());
}
}
This will never throw a RunTimeException because your Widgit instance variable w remains null until the constructor code has executed. While your main thread is sleeping in the Widgit constructor, your Checker instance is hitting NullPointerException constantly as the w variable is still null. When your main thread finishes construction, the two int variables in Widgit are equal.

Categories

Resources