2012-05-09 4 views
7

어제 Java에서 시험을 보았습니다. 정말 모호한 것처럼 보입니다.비 정적 생성자에 대한 정적 메서드 액세스?

규칙은 간단하다 :

  1. 정적 메소드는 비 정적 메소드를 호출 할 수 없다.
  2. 생성자는 반환 유형이없는 메서드과 비슷합니다.

    public class Main { 
        public static void main(String[] args) { 
         Main p = new Main(); 
         k(); 
        } 
    
        protected Main() { 
         System.out.print("1234"); 
        } 
    
        protected void k() { 
        } 
    } 
    
    Main p = new Main() line prints 1234 
    k() line raises error 
    

왜 이런 일이 않았다 ? 위의 Java 규칙과 충돌하지 않습니까?

+3

정적 메서드에서 생성자를 호출 할 수없는 경우 개체를 구성 할 수 없습니다. –

답변

10

1 - 정적 메서드는 비 정적 메서드를 호출 할 수 없습니다.

그들이 할 수 있지만,이에 메소드를 호출하는 객체가 필요 확인합니다.

정적 메서드에서는 foo() (this.foo()에 해당)이 유효하지 않으므로 this 참조가 없습니다.

2 - 생성자는 반환 유형이없는 일종의 메소드입니다. 그들이 compared to methods을해야하는 경우

, 나는 생성자 (참 생성자 내부 this 참조가 있기 때문에) 비 정적 방법에 가까운 말할 것입니다.

이보기에서 정적 메서드가 아무 문제없이 생성자를 호출 할 수있는 이유는 분명합니다.


그래서, 그것을 정리해 :

Main p = new Main(); 

괜찮습니다, new Main() 때문에 기존의 객체에 의존하지 않습니다. 이 this.k()에 해당하고 this이 (정적)의 주요 방법으로 사용할 수 없습니다 때문에

k(); 

괜찮 없습니다.

+0

사람들은 항상'새로운 main()'이 단순한 생성자 호출이 아니라는 사실을 알고 있습니다. 단항 연산자'new'를 적용하면서 호출 할 생성자를 많이 **의 일부로 지정합니다 더 넓은 할당 + 초기화 절차 **. –

+0

@MarkoTopolnik, JLS 참조? – aioobe

+0

그것은 분명하기 때문에 정말 필요합니까? 'new'를 적용하면 ** 힙에서 메모리를 할당합니다 ** - 생성자에는 기록되지 않습니다.** 모든 인스턴스 이니셜 라이저 **를 호출합니다 - 또 다른 사실은 분명합니다. 이는 생성자 코드에서 아무 것도 쓰여지지 않았습니다. 또한 호출자가 아닌 암시 적 코드에 의해 갑자기 정의 된 'this'를 사용하여 생성자를 호출합니다. 생성자는 실제로 콜백 일뿐입니다. –

4

아니요.이 점에있어서 생성자는 일반적인 방법이 아닙니다. 생성자의 핵심은 클래스의 새 인스턴스를 만드는 것입니다.

그래서 정적 범위에서도 호출 할 수 있습니다. 생각해보십시오. 클래스의 새 인스턴스를 만들기 위해 클래스의 기존 인스턴스가 필요하면 간단하게 인스턴스를 생성 할 수 없습니다.

몇 해명 :

정적 메소드는 비 정적 메소드를 호출 할 수 없다.

아닙니다. static 메서드 내에서 nonstatic 메서드를 호출 할 수 있습니다. 범위이 클래스의 특정 개체에만 필요합니다. 나는.

p.k(); 

위의 코드 샘플에서 완벽하게 작동합니다.

k(); 

인스턴스 (비 정적)에있어서 내부의 미세한 것이다. 그리고 그것은

this.k(); 

함축 this 클래스의 현재 인스턴스를 참조에 해당하는 것입니다. 컴파일러가 인스턴스 메서드 내에서 k()과 같은 비정규 호출을 발견하면 자동으로 this.으로 범위를 지정합니다. 그러나 정적 메서드는 클래스의 인스턴스에 연결되어 있지 않으므로 정적 메서드 내에서 this을 참조 할 수 없습니다. 따라서 인스턴스 메소드를 호출하기 위해 명시 적으로 클래스의 인스턴스 이름을 지정해야합니다.

5

규칙은 간단하다 :
1 - 정적 메소드는 비 정적 메소드를 호출 할 수 없다.

그건 사실이 아닙니다. 정적 메서드 은 "대상"참조를 통해 비 정적 메서드를 호출 할 수 있습니다. 예를 들어,이 정적 메서드에서 괜찮 :

Integer x = Integer.valueOf(10); 
int y = x.intValue(); // Instance method! 

실제 점은 "정적 메서드 내에 this 참조 없다"입니다.

2 - 생성자는 반환 유형이없는 일종의 메소드입니다.

솔직히 말해서 정말 유용한 모델은 아닙니다. 더 많은 것 (호출자의 관점에서) 생성자는 선언 클래스와 동일한 반환 유형을 가진 정적 메서드로 간주하지만 어떤 방법 으로든 완벽한 모델이 아닙니다.

생성자를 다른 유형의 멤버로 생각하는 것이 좋습니다. 생성자와 메서드를 숨기려고하는 대신에 생성자와 메서드의 차이점을 수용하십시오.

+0

개체 초기화의 일부로 호출되는 void 반환 콜백에 생성자를 적용하면 어떻습니까? 그 간접적 인 수준은 내 마음에, 사람들을 벗어나 잘못된 가정을 일으키는 것입니다. –

+0

@MarkoTopolnik : 호출자 *의 관점에서 생각하고 있는지 여부에 달려 있습니다 (이 경우 "void-returning"은 결과를 사용할 수 있으므로 말도 안됩니다) 또는 구현 * (in 어느 경우에 그것은 이해된다). 나는 방법에 대해 비틀 거리는 비유를 만들기보다는 그 자체의 유형으로 생각하는 것을 선호합니다. –

+0

호출자가 단지'new'를 적용하고 어떤 함수도 호출하지 않는다는 사실을 고려하면 넌센스가 아닙니다. 그것은 사실 내 요점입니다 - 하나는 새로운 것을 존중해야하며 그것을 보지 않아야합니다. 해당 연산자의 반환 값은 참조이며 생성자는 여전히 'void'를 반환하는 콜백으로 간주 할 수 있습니다. 유추는 지금까지 갈 수 있지만, 새로운 것을 배울 때 여전히 도움이된다는 데 동의합니다. –

관련 문제