본문 바로가기

자바

8.3 Field Declarations (2)

8.3.1 Field Modifiers

 

8.3.1.1 static Fields

결과:

(2, 2)
0
true
1

 

Example 8.3.1.1-2. Hiding of Class Variables

package main;

public class Test extends Point {
	static double x = 4.7;
	
	public static void main(String[] args) {
		new Test().printX();
	}
	
	void printX() {
		System.out.println(x + " " + super.x);
	}
}

class Point {
	static int x = 2;
}

결과:

4.7 2

Test 클래스의 x의 선언은 Point 클래스의 x의 정의를 숨기기 때문에,

Test 클래스는 그것의 슈퍼클래스인 Point 클래스의 x를 상속받지 않는다.

 

package main;

public class Test extends Point {
	public static void main(String[] args) {
		new Test().printX();
	}
	
	void printX() {
		System.out.println(x + " " + super.x);
	}
}

class Point {
	static int x = 2;
}

결과:

2 2

 

Example 8.3.1.1-3. Hiding of Instance Variables

package main;

public class Test extends Point {
	double x = 4.7;
	
	void printBoth() {
		System.out.println(x + " " + super.x);
	}
	
	public static void main(String[] args) {
		Test sample = new Test();
		sample.printBoth();
		System.out.println(sample.x + " " + ((Point)sample).x);
	}
}

class Point {
	int x = 2;
}

결과:

4.7 2
4.7 2

 

 

8.3.1.2 final Fields

 

8.3.1.3 transient Fields

 

8.3.1.4 volatile Fields

The java programming language allows threads to access shared variables.

As a rule, to ensure that shared variables are consistency and reliably updated,

a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.

 

The java programming language provides a second mechanism, volatile fields,

that is more convenient than locking for some purposes.

 

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the vaiable.

 

It is a compile-time error if a final variable is also declared volatile.

 

Example 8.3.1.4-1. volatile Fields

If, in the following example, one thread repeatedly calls the method one(but no more than Integer.MAX_VALUE time in all), and another thread repeatedly calls the method two:

package main;

public class Test {
	static int i = 0, j = 0;
	
	static void one() {
		i++;
		j++;
	}
	
	static void two() {
		System.out.println("i = " + i + " j = " + j);
	}
}

then method two could occasionally print a value for j that is greater than the value of i,

because the example includes no synchronization and, under the rules explained in $17.4,

the shared values of i and j might be updated out of order.

 

One way to prevent this out-or-order behavior would be to declare methods one and two to be synchronized($8.4.3.6):

package main;

public class Test {
	static int i = 0, j = 0;
	
	static synchronized void one() {
		i++;
		j++;
	}
	
	static synchronized void two() {
		System.out.println("i = " + i + " j = " + j);
	}
}

This prevents method one and method two from being executed concurrently, and furthermore guarantees that the shared values of i and j are both updated before method one returns.

Therefore method two never observes a value for j greater than that for i;

indeed, it always observes the same value for i and j.

 

Another approach would be to declare i and j to be volatile:

package main;

public class Test {
	static volatile int i = 0, j = 0;
	
	static void one() {
		i++;
		j++;
	}
	
	static void two() {
		System.out.println("i = " + i + " j = " + j);
	}
}

This allows method one and method two to be executed conccurently, but guarantees that accesses to the shared values for i and j occur exactly as many times, and in exactly the same order, as they appear to occur during execution of the program text by each thread.