Java 해혹 5 - 클래스 수수께끼
。main , ? 。 ? ?
public class Confusing {
private Confusing(Object o) {
System.out.println("Object");
}
private Confusing(double[] dArray) {
System.out.println("double array");
}
public static void main(String[] args) {
new Confusing(null);
}
}
결과: 이 프로그램이 인쇄한 것은 더블array입니다.이유: Java의 재부팅 확인 프로세스가 2단계로 실행됩니다.첫 번째 단계는 얻을 수 있고 응용할 수 있는 모든 방법이나 구조기를 선택한다.2단계는 1단계에서 선택한 방법이나 구조기 중에서 가장 정확한 것을 선택한다.만약에 한 방법이나 구조기가 다른 방법이나 구조기에 전달되는 모든 매개 변수를 받아들일 수 있다면 우리는 첫 번째 방법이 두 번째 방법보다 정확성이 부족하다고 말한다[JLS 15.12.2.5].우리 프로그램에서 두 개의 구조기는 모두 얻을 수 있고 응용할 수 있다.구조자 Confusing(Object)은 Confusing(double[])에 전달되는 모든 매개 변수를 받아들일 수 있기 때문에 Confusing(Object)은 상대적으로 정확성이 부족하다.(모든 더블 그룹은 하나의 Object이지만 모든 Object가 반드시 하나의 더블 그룹은 아니다.)따라서 가장 정확한 구조기는 바로 Confusing(double[])이다. 이것은 왜 프로그램이 이런 출력을 만들어 냈는지 설명한다.
수수께끼제 고양이가 개가 됐어요.
Counter 。 ?
class Counter {
private static int count = 0;
public static final synchronized void increment() {
count++;
}
public static final synchronized int getCount() {
return count;
}
}
class Dog extends Counter {
public Dog() { }
public void woof() { increment(); }
}
class Cat extends Counter {
public Cat() { }
public void meow() { increment(); }
}
public class Ruckus {
public static void main(String[] args) {
Dog dogs[] = { new Dog(), new Dog() };
for (int i = 0; i < dogs.length; i++)
dogs[i].woof();
Cat cats[] = { new Cat(), new Cat(), new Cat() };
for (int i = 0; i < cats.length; i++)
cats[i].meow();
System.out.print(Dog.getCount() + " woofs and ");
System.out.println(Cat.getCount() + " meows");
}
제목: 5 woofs and 5 meows원인: 공유count;
수수께끼 48: 내가 얻은 것은 모두 정적이다
。 , , , 。 , ?
class Dog {
public static void bark() {
System.out.print("woof ");
}
}
class Basenji extends Dog {
public static void bark() { }
}
public class Bark {
public static void main(String args[]) {
Dog woofer = new Dog();
Dog nipper = new Basenji();
woofer.bark();
nipper.bark();
}
}
제목:woofwoof로 인쇄된 것 발견원인: 문제는 bark는 정적 방법이지만 정적 방법의 호출에는 어떠한 동적 분배 메커니즘도 존재하지 않는다는 것이다.
프로그램이 정적 방법을 호출할 때 호출될 방법은 모두 컴파일할 때 선택된다. 이러한 선택은 수식자의 컴파일러 유형을 바탕으로 한 것이다. 수식자의 컴파일러 유형은 우리가 제시한 방법 호출 표현식의 원점 왼쪽 부분의 이름이다.본 안건에서 두 가지 방법으로 호출된 수식자는 각각 변수 우퍼와 니퍼이며, 모두 Dog 유형으로 성명되었다.그것들은 같은 컴파일러 유형을 가지고 있기 때문에 컴파일러는 그것들을 같은 방법으로 호출한다: Dog.bark.
수수께끼
, “ ” 。 , 。 Calendar.getInstance().get(Calendar.YEAR) , 。 , ?
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private final int beltSize;
private static final int CURRENT_YEAR =
Calendar.getInstance().get(Calendar.YEAR);
private Elvis() {
beltSize = CURRENT_YEAR - 1930;
}
public int beltSize() {
return beltSize;
}
public static void main(String[] args) {
System.out.println("Elvis wears a size " +
INSTANCE.beltSize() + " belt.");
}
}
제목: Elvis wears a size - 1930 belt를 인쇄합니다.원인: Elvis 클래스의 초기화는 가상 컴퓨터가main 방법을 호출해서 터치합니다.먼저 정적 도메인이 기본값[JLS 4.12.5]으로 설정되고 INSTANCE 도메인이 null, CURRENT 로 설정됩니다.YEAR가 0으로 설정됩니다.다음에 정적 영역 초기기는 나타나는 순서에 따라 실행됩니다.첫 번째 정적 영역은 INSTANCE입니다. 이 값은 Elvis () 구조기를 호출해서 계산됩니다.이 구조기는 정적 영역과 관련된 CURRENT 를 사용합니다.YEAR의 표현식으로 beltSize를 초기화합니다.일반적으로 정적 영역을 읽는 것은 클래스가 초기화되는 이벤트 중 하나이지만, 우리는 이미 Elvis 클래스를 초기화하고 있습니다.반복되는 초기화 시도는 [JLS 12.4.2, 3단계]에서 무시됩니다.따라서 CURRENTYEAR 값은 여전히 기본값인 0입니다.엘비스의 벨트 사이즈가 -1930으로 바뀐 이유다.
수수께끼
Java :instanceof 。 ?
public class Type1 {
public static void main(String[] args) {
String s = null;
System.out.println(s instanceof String);
}
}
public class Type2 {
public static void main(String[] args) {
System.out.println(new Type2() instanceof String);
}
}
public class Type3 {
public static void main(String args[]) {
Type3 t3 = (Type3) new Object();
}
}
제목:첫 번째 프로그램인 Type1은 빈 대상이 인용할 때 사용할 instanceof 조작부호를 보여 줍니다.비록null은 모든 인용 형식에 대해 하위 형식이지만, instanceof 조작부호는 왼쪽 조작수가null일 때false로 정의됩니다.따라서 Type1은 false를 인쇄합니다.이것은 실천에서 매우 유용한 행위로 증명되었다.만약 instanceof가 대상이 특정한 유형의 실례를 인용한다고 알려준다면, 이 유형을 이 유형으로 바꾸고, 이 유형의 방법을 호출할 수 있으며, ClassCastException이나 NullPointerException 이상을 던질 염려가 없다.
,Type2, instanceof , 。 false。 ,Type2 String , , ? ,instanceof , :
Type2.java:3: inconvertible types
found : Type2, required: java.lang.String
System.out.println(new Type2() instanceof String);
^
instanceof : , [JLS 15.20.2, 15.16, 5.5]。Type2 String , instanceof 。 instanceof , 。
,Type3, , 。 instanceof , , 。 , , new Object() Type3 。 , ClassCastException 。
51: ?
(value class), 。 , 。 。 , ?
class Point {
protected final int x, y;
private final String name; // Cached at construction time
Point(int x, int y) {
this.x = x;
this.y = y;
name = makeName();
}
protected String makeName() {
return "[" + x + "," + y + "]";
}
public final String toString() {
return name;
}
}
public class ColorPoint extends Point {
private final String color;
ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
protected String makeName() {
return super.makeName() + ":" + color;
}
public static void main(String[] args) {
System.out.println(new ColorPoint(4, 2, "purple"));
}
}
제목:[4,2]:null
원인:final 형식의 실례역이 부여되기 전에 그 값을 사용할 수 있는 가능성이 존재하지만, 이 때 그 값이 포함된 것은 그 종류에 속하는 부족한 값이다.
수수께끼 , 。 , ? : , , 1 n n(n+1)/2。
class Cache {
static {
initializeIfNecessary();
}
private static int sum;
public static int getSum() {
initializeIfNecessary();
return sum;
}
private static boolean initialized = false;
private static synchronized void initializeIfNecessary() {
if (!initialized) {
for (int i = 0; i < 100; i++)
sum += i;
initialized = true;
}
}
}
public class Client {
public static void main(String[] args) {
System.out.println(Cache.getSum());
}
}
제목: 출력 9900
이유:
클래스 초기화는 정적 초기화가 원본 코드에 나타나는 순서에 따라 이 초기화를 실행합니다.Cache 클래스에는 두 개의 정적 초기기가 있습니다. 클래스 맨 위에 있는static 문장 블록과 정적 영역인itialized의 초기화입니다.정적 문장 블록이 먼저 나타납니다. 방법인itializeIfNecessary를 호출했습니다. 이 방법은initialized 영역을 테스트합니다.이 필드는 아직 아무런 값도 부여되지 않았기 때문에, 부족한 부울 값false를 가지고 있습니다.이와 유사하게,sum는 부족한 int값 0을 가지고 있습니다.따라서, intialize IfNecessary 방법은 당신이 원하는 행동을 실행합니다. 4950을sum에 추가하고, intialized를true로 설정합니다.정적 문장 블록이 실행된 후, initialized 영역의 정적 초기화는false로 설정하여Cache의 클래스를 초기화합니다.유감스럽게도sum는 현재 정확한 캐시 값을 포함하고 있지만, initialized는false:Cache류의 두 가지 관건적인 상태가 동기화되지 않았습니다.
수수께끼
대략!
퀴즈 54:Null과 Void Hello World 。 , ?
public class Null {
public static void greet() {
System.out.println("Hello world!");
}
public static void main(String[] args) {
((Null) null).greet();
}
}
제목: "Hello World!"출력
이유: Null.greet은 정적 방법입니다.수수께끼 48에서 보듯이 정적 방법의 호출에서 표현식을 한정부호로 사용하는 것은 좋은 생각이 아니다. 이것이 바로 문제다.표현식의 값이 인용된 대상의 운행기 유형은 어떤 방법이 호출될지 결정할 때 아무런 작용도 하지 않을 뿐만 아니라, 대상에 표지가 있으면 그 표지도 아무런 작용도 하지 않는다.이 예에는 어떤 대상도 없지만, 이것은 결코 어떤 차이도 일으키지 않는다.정적 방법이 호출된 한정 표현식은 계산할 수 있지만, 그 값은 무시됩니다.값이 비어 있지 않은 것을 요구하는 제한이 없습니다.
수수께끼 , , , 。 ,Creature , Creator , Creature 。 , ?
public class Creator {
public static void main(String[] args) {
for (int i = 0; i < 100; i++)
Creature creature = new Creature();
System.out.println(Creature.numCreated());
}
}
class Creature {
private static long numCreated = 0;
public Creature() {
numCreated++;
}
public static long numCreated() {
return numCreated;
}
}
제목: 컴파일 실패;
이유:
로컬 변수 성명은 하나의 문장처럼 보이지만 기술적으로는 그렇지 않다.로컬 변수 선언문(localvariable declaration statement)[JLS 14.4]이어야 합니다.Java 언어 규범에서는 로컬 변수 성명문이 for,while,do 순환에서 [JLS14.12-14]를 반복해서 실행하는 것을 허용하지 않습니다.로컬 변수 성명은 하나의 문장으로 하나의 문장 블록에만 직접 나타날 수 있습니다.(하나의 문장 블록은 한 쌍의 괄호와 이 괄호전에 포함된 문장과 성명으로 구성된다.)해결 방법:
이 문제를 정정할 수 있는 두 가지 방법이 있다.가장 명백한 방법은 이 성명을 하나의 문장 블록에 넣는 것이다.
for (int i = 0; i < 100; i++) {
Creature creature = new Creature();
}
그러나 이 프로그램은 로컬 변수creature를 사용하지 않았습니다.따라서 새 작성 객체에 대한 참조가 버려지고 있음을 강조하기 위해 이 선언을 수식되지 않은 구조자 호출로 대체하는 것이 더 실질적입니다.
for (int i = 0; i < 100; i++)
new Creature();
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.