385

구체적으로이 코드를 시도했습니다.

package hello;

public class Hello {

    Clock clock = new Clock();

    public static void main(String args[]) {
        clock.sayTime();
    }
}

그러나 그것은 오류를 주었다.

정적 메서드 main에서 비 정적 필드에 액세스 할 수 없습니다.

그래서 나는clock이에:

static Clock clock = new Clock();

그리고 효과가있었습니다. 그 키워드를 선언 앞에 두는 것은 무엇을 의미합니까? 객체에 대해 수행 할 수있는 작업의 관점에서 정확히 무엇을하고 제한합니까?


  • 다시 한번 CLASSLOADER 당 클래스 당 하나의 정적 인스턴스가 있음을 기억하십시오. - Javamann

21 답변


565

static멤버는 특정 인스턴스 대신 클래스에 속합니다.

그것은하나의 인스턴스 만static입력란이 존재합니다.[1]백만 개의 클래스 인스턴스를 만들거나 아무 것도 만들지 않더라도 마찬가지입니다. 그것은 모든 경우에 의해 공유 될 것입니다.

이후static메소드도 특정 인스턴스에 속하지 않으므로 인스턴스 멤버를 참조 할 수 없습니다. 주어진 예에서,main어떤 인스턴스가Hello클래스 (따라서 어떤Clock클래스) 참조해야합니다.static회원들만 참조 할 수 있습니다.static회원. 인스턴스 멤버는 물론 액세스 할 수 있습니다.static회원.

사이드 노트 :당연하지,static멤버는 인스턴스 멤버에 액세스 할 수 있습니다.객체 참조를 통해.

예:

public class Example {
    private static boolean staticField;
    private boolean instanceField;
    public static void main(String[] args) {
        // a static method can access static fields
        staticField = true;

        // a static method can access instance fields through an object reference
        Example instance = new Example();
        instance.instanceField = true;
    }

[1] : 런타임 특성에 따라 ClassLoader 또는 AppDomain 또는 스레드 당 하나가 될 수 있지만 그 점 옆에 있습니다.


  • .NET에서 [ThreadStatic] 특성을 사용하여이 동작을 수정할 수도 있습니다.이 특성은 정적 스레드를 특정 스레드에 대해 로컬로 만듭니다. - TheSoftwareJedi
  • 그래서 정적 javascripts 프로토 타입 같은가요? - super
  • 아니, 그건 다르다. JS 프로토 타입은 수퍼 클래스에 가깝습니다. - Adriaan Koster
  • 나는 이것이 오래된 게시물이지만 나 같은 초보자를위한 도움이 될 수 있습니다 알아요.stackoverflow.com/questions/7026507/… - user3526905
  • private var이므로 instance.instanceField에 액세스 할 수 없습니까? 또는 클래스의 내부 클래스에서 인스턴스를 생성했기 때문에 유효합니까? 재귀적인 악몽처럼 들리지만 자바 초보자입니다. - Matt Corby

125

Hello라는 "클럭"인스턴스가 하나만 존재한다는 것을 의미합니다. "Hello"클래스의 각각의 인스턴스마다 하나가 아니라, 모든 인스턴스에서 공통적으로 공유되는 "클럭"참조가 하나 있다는 것을 의미합니다. "Hello"클래스.

따라서 코드에서 "새 Hello"를 수행하려면 다음을 수행하십시오. A- 첫 번째 시나리오에서는 (변경 전, "정적"을 사용하지 않고) "새 Hello"가 호출 될 때마다 새 시계를 만들지 만 B- 두 번째 시나리오 (변경 후 "정적"사용)에서 모든 "새 Hello"인스턴스는 처음 생성 된 동일한 "시계"참조를 공유하고 사용합니다.

메인의 바깥 쪽에서 "시계"가 필요하다면, 이것은 잘 작동 할 것입니다 :

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}


  • 이것이 더 일반적인 방법입니다. 그만큼main()루틴은 자체 포함되어야합니다. - Jason S
  • 두 번째 인스턴스에서는 주 메서드가 호출 될 때마다 Clock 인스턴스가 새로 생성됩니다. - Click Upvote
  • 두 번째 인스턴스에서는 clock static으로 한 번만 생성합니다. 내 예제에서, 클럭은 메인 내에 있고, 그렇다면 메인이 호출 될 때마다 새로운 클럭을 생성합니다. 그러나 일반적으로 메인은 프로그램 시작시에만 한 번만 호출되며 종료하면 모든 것이 자유 로워집니다. - Paul Tomblin
  • 기본 방법에서 어떻게 새 시계를 만들 수 있나요? 당신이 말했듯이 메인이 호출 될 때마다 새로운 것을 만들지 만, 하나의 메인 메소드 만 존재합니다. 주요 방법이 다른 클럭 인스턴스를 참조 할 수있는 방법은 무엇입니까? 주 메뉴에서 시계의 새 인스턴스를 만들고이를 사용하는 방법 (예 : sayTime ())을 사용하는 것이 가능한지 이해하기는 다소 어렵지만 인스턴스를 주 메뉴에서 제외하고 sayTime (). 메인이 한 번 호출 될 때 모든 것이 어떻게 자유로운가? @PaulTomblin - user5621266
  • @ user5621266 나는 오직main왜냐하면 OP가했기 때문입니다. 대신에 다른 곳에서 호출 된 public 메서드이고 Hello 클래스가 두 번 이상 인스턴스화 된 경우 각 Hello 인스턴스에 대해 Clock 인스턴스를 만들 수 있습니다.clock정적이었다. - Paul Tomblin

93

그만큼static키워드 란 무언가 (필드, 메소드 또는 중첩 된 클래스)가유형어떤 특정한 것보다는 오히려유형의. 예를 들어,Math.sin(...)어떤 경우도없이Math계급, 실제로 당신캔트의 인스턴스를 생성한다.Math수업.

자세한 내용은오라클의 자바 튜토리얼 관련 비트.


Java 불행히도허락하다인스턴스 멤버 인 것처럼 정적 멤버에 액세스 할 수 있습니다.

// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);

그것은 그것을 만든다.보기마치sleep인스턴스 메소드이지만 실제로는 정적 메소드입니다.항상현재 스레드를 잠자기 상태로 만듭니다. 이 코드를 호출 코드에서 명확하게 만드는 것이 더 좋습니다.

// Clearer
Thread.sleep(5000);


  • 또 다른 예 : System.out.println ()외모클래스 메소드와 같지만 사실 인스턴스 메소드입니다. out은 System 클래스의 PrintStream 인스턴스입니다. - Jiahui Zhang
  • @LeslieCheung : 아니, 나에게 수업 방법처럼 보이지 않는다.System.out나에게 유형 이름을 사용하고 싶지 않습니다. - Jon Skeet

38

그만큼staticJava에서 keyword는 변수 또는 함수가 해당 클래스의 모든 인스턴스간에 공유된다는 것을 의미합니다.유형실제 객체 자체는 아닙니다.

그래서 변수가 있다면 :private static int i = 0;당신은 그것을 증가시킵니다 (i++) 변경 사항은 모든 인스턴스에 반영됩니다.i모든 경우에 1이됩니다.

정적 메서드는 객체를 인스턴스화하지 않고 사용할 수 있습니다.


  • " 모든 인스턴스간에 공유 됨 " IMO가 잘못된 인상을주었습니다.해야 할 것객체의 인스턴스가 있어야합니다. - Jon Skeet
  • (반면에 실제로는 필요하지 않지만어떤정적 필드 등이유형.) - Jon Skeet
  • @ 존 Skeet 정적 개체 유형이 아닌 속해? 더 자세하게 말할 수 있습니까? 데이터 유형과 유사하게 입력하십시오 : int, double, ...? - truongnm
  • @truongnm : 변수 / 메소드를 선언하는 클래스에 입력하십시오. - Jon Skeet

22

정적 멤버의 기본 사용법 ...

public class Hello
{
    // value / method
    public static String staticValue;
    public String nonStaticValue;
}

class A
{
    Hello hello = new Hello();
    hello.staticValue = "abc";
    hello.nonStaticValue = "xyz";
}

class B
{
    Hello hello2 = new Hello(); // here staticValue = "abc"
    hello2.staticValue; // will have value of "abc"
    hello2.nonStaticValue; // will have value of null
}

그래서 클래스 인스턴스 Hello를 다른 클래스로 보내지 않고 모든 클래스 멤버에서 값을 공유 할 수 있습니다. 그리고 부 정적 클래스 인스턴스를 만들 필요가 없습니다.

Hello hello = new Hello();
hello.staticValue = "abc";

클래스 이름별로 정적 값이나 메소드를 호출 할 수 있습니다.

Hello.staticValue = "abc";


19

Static은 클래스와 연관된 메소드 나 변수를 사용하기 위해 클래스의 인스턴스를 작성할 필요가 없다는 것을 의미합니다. 귀하의 예에서는 다음과 같이 전화 할 수 있습니다.

Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class

직접 대신에 :

Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable

정적 메서드 (클래스에 속함) 내부에서는 클래스의 인스턴스화에 따라 값이 달라지기 때문에 정적이 아닌 멤버에는 액세스 할 수 없습니다. 인스턴스 멤버 인 비 정적 Clock 객체는 Hello 클래스의 각 인스턴스에 대해 다른 값 / 참조를 가지므로 클래스의 정적 부분에서 액세스 할 수 없습니다.


15

Java의 정적 :

정적은 비 접근 수정 자입니다. static 키워드는 클래스의 인스턴스보다 클래스에 속합니다. 변수 또는 메소드를 클래스에 첨부하는 데 사용할 수 있습니다.

정적 키워드는 다음과 함께 사용할 수 있습니다 :

방법

변하기 쉬운

다른 클래스 내에 상자가 짜 넣어지고있는 클래스

초기화 블록

다음과 함께 사용할 수 없습니다 :

클래스 (중첩되지 않음)

건설자

인터페이스

메서드 로컬 내부 클래스 (차이 및 중첩 된 클래스)

내부 클래스 메서드

인스턴스 변수

지역 변수

예:

다음 예제를 상상해보십시오.count라는 이름의 인스턴스 변수어느 생성자에서 증가했다 :

package pkg;

class StaticExample {
    int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

산출:

1 1 1

인스턴스 변수는 객체 생성시 메모리를 가져 오므로 각 객체는 인스턴스 변수의 사본을 가지며, 증가하면 다른 객체에 반영되지 않습니다.

이제 우리가인스턴스 변수 수를 정적으로 변경하십시오.하나는 프로그램이 다른 출력을 생성합니다 :

package pkg;

class StaticExample {
    static int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

산출:

1 2 3

이 경우 정적 변수는 메모리를 한 번만 가져오고, 객체가 정적 변수의 값을 변경하면 해당 값이 유지됩니다.

최종 정적 :

다음과 같이 선언 된 전역 변수최종 및 정적전체 실행에 대해 변경되지 않은 상태로 유지됩니다. 왜냐하면 정적 멤버는 클래스 메모리에 저장되기 때문에 전체 실행에서 한 번만로드됩니다. 그것들은 그 클래스의 모든 객체에 공통적입니다. 정적 변수를 final로 선언하면 모든 객체가 최종 값이 될 수 없습니다. 따라서 final 및 static으로 선언 된 변수는 상수라고도합니다. 인터페이스의 모든 필드는 기본적으로 최종 및 정적이기 때문에 상수라고합니다.

enter image description here

그림 자료 :최종 정적


13

이 논의는 클래스 로더 고려 사항을 지금까지 무시했습니다. 엄밀히 말하면, Java 정적 필드는 주어진 클래스에 대해 클래스의 모든 인스턴스간에 공유됩니다.클래스 로더.


  • 이것은 Apocalisp에 의해 Merhdad의 대답에 대한 언급에서 언급되었습니다. - Zach Langley
  • 좋은 지적. 많은 사람들이 이것을 모르고 있지만 일단 클래스 로더를 망치면 매우 중요해진다. - sleske
  • 이것은 모두 사실이지만 질문에 답을하지 못합니다. 그것은 코멘트로 게시되어 있어야합니다. - user207421

12

기존 답변에 추가하려면 그림으로 시도해보십시오.

모든 저축 예금에는 2 %의 이자율이 적용됩니다. 그러므로 그것은공전.

잔액이 있어야합니다.개인, 그래서 그것은아니공전.

enter image description here


7

필드는 클래스 또는 클래스의 인스턴스에 할당 될 수 있습니다. 기본적으로 필드는 인스턴스 변수입니다. 사용하여static필드가 클래스 변수가되므로 하나만 존재합니다.clock. 한 곳에서 변경을하면 어디서나 볼 수 있습니다. 인스턴스 변수는 서로 독립적으로 변경됩니다.


6

자바에서는static키워드는 단순히 다음을 나타내는 것으로 간주 할 수 있습니다.

"특정 인스턴스에 관계없이"

당신이 생각하면static이런 식으로, 그것이 발생하는 다양한 맥락에서 그것의 사용을 이해하는 것이 더 쉬워진다 :

  • 에이static필드는 특정 인스턴스가 아닌 클래스에 속한 필드입니다.

  • 에이static방법은 개념이없는 방법이다.this; 클래스에 정의되어 있으며 참조가 전달되지 않는 한 해당 클래스의 특정 인스턴스에 대해 알지 못합니다.

  • 에이static멤버 클래스는 둘러싼 클래스 인스턴스에 대한 개념이나 지식이없는 중첩 클래스입니다 (해당 클래스 인스턴스에 대한 참조가 전달되지 않은 경우).


5

Static은 시계 멤버를 인스턴스 멤버가 아닌 클래스 멤버로 만듭니다. static 키워드가 없으면 Hello 클래스 (클럭 멤버 변수가 있음)의 인스턴스를 만들어야합니다. 예 :

Hello hello = new Hello();
hello.clock.sayTime();


5

정적 메소드는 정의 된 클래스의 인스턴스 변수를 사용하지 않습니다. 차이점에 대한 아주 좋은 설명은 다음에서 찾을 수 있습니다.이 페이지


  • 링크가 더 이상 작동하지 않습니다. - John

5

나는 "도우미"클래스에서 정적 메서드 (가능한 경우에만)에 대한 선호도를 개발했습니다.

호출 클래스는 도우미 클래스의 다른 멤버 (인스턴스) 변수를 생성 할 필요가 없습니다. 헬퍼 클래스의 메서드를 호출하면됩니다. 또한 더 이상 생성자가 필요없고 멤버 (인스턴스) 변수가 필요 없기 때문에 도우미 클래스가 개선되었습니다.

아마 다른 장점이 있습니다.


5

키워드static필드 나 메소드를 인스턴스가 아닌 클래스 자체에 속하는 것으로 나타내는 데 사용됩니다. 코드를 사용하여 객체가Clock정적 인 경우Hello수업에서 이걸 나눌거야.Clock데이터 회원 (필드) 공통. 정적이 아닌 경우,Hello독특한 것을 가질 수있다.Clock들.

문제는본관수업에 대한 방법Hello그래서 당신은 코드를 실행할 수 있습니다. 여기서 문제는본관메서드는 정적이므로 내부의 비 정적 필드 나 메서드를 참조 할 수 없습니다. 다음 두 가지 방법으로 문제를 해결할 수 있습니다.

  1. 모든 분야와 방법을Hello클래스 내부에서 참조 될 수 있도록 정적 인 클래스본관방법. 이것은 실제로 할 수있는 좋은 일이 아닙니다 (또는 틀린 이유가 필드와 정적 메소드를 정적으로 만듭니다)
  2. 인스턴스를 생성하십시오.Hello클래스의 메소드를 호출하고 처음부터 의도했던대로 모든 필드와 메소드에 액세스합니다.

이는 코드를 다음과 같이 변경했음을 의미합니다.

package hello;

public class Hello {

    private Clock clock = new Clock();

    public Clock getClock() {
        return clock;
    }

    public static void main(String args[]) {
        Hello hello = new Hello();
        hello.getClock().sayTime();
    }
}


3

"this"포인터가없는 정적 멤버도 생각할 수 있습니다. 모든 인스턴스간에 공유됩니다.


3

정적 개념 이해

public class StaticPractise1 {
    public static void main(String[] args) {
        StaticPractise2 staticPractise2 = new StaticPractise2();
        staticPractise2.printUddhav(); //true
        StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */

        StaticPractise2.printUddhavsStatic1(); //true
        staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static  things and it organizes in its own heap. So, class static methods, object can't reference */

    }
}

이급

public class StaticPractise2 {
    public static void printUddhavsStatic1() {
        System.out.println("Uddhav");
    }

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}


2

main()두 가지 근본적인 제한이있는 정적 메서드입니다.

  1. 정적 메서드는 비 정적 데이터 멤버를 사용하거나 비 정적 메서드를 직접 호출 할 수 없습니다.
  2. this()super()정적 컨텍스트에서는 사용할 수 없습니다.

    class A {  
        int a = 40; //non static
        public static void main(String args[]) {  
            System.out.println(a);  
        }  
    }
    

출력 : 컴파일 시간 오류


1

정적 변수 정적 메서드에서만 액세스 할 수 있으므로 정적 변수를 선언하면 getter 및 setter 메서드가 정적 메서드가됩니다.

정적 메소드는 클래스 이름을 사용하여 액세스 할 수있는 클래스 레벨입니다.

다음은 정적 변수 게터 및 세터의 예입니다.

public class Static 
{

    private static String owner;
    private static int rent;
    private String car;
    public String getCar() {
        return car;
    }
    public void setCar(String car) {
        this.car = car;
    }
    public static int getRent() {
        return rent;
    }
    public static void setRent(int rent) {
        Static.rent = rent;
    }
    public static String getOwner() {
        return owner;
    }

    public static void setOwner(String owner) {
        Static.owner = owner;
    }

}


1

//Here is an example 

public class StaticClass 
{
    static int version;
    public void printVersion() {
         System.out.println(version);
    }
}

public class MainClass 
{
    public static void main(String args[]) {  
        StaticClass staticVar1 = new StaticClass();
        staticVar1.version = 10;
        staticVar1.printVersion() // Output 10

        StaticClass staticVar2 = new StaticClass();
        staticVar2.printVersion() // Output 10
        staticVar2.version = 20;
        staticVar2.printVersion() // Output 20
        staticVar1.printVersion() // Output 20
    }
}


0

어떤 프로젝트를 실행할 때 먼저 정적 인 것들을로드합니다 (변수, 메소드, 블록 ..).

이 프로젝트를 실행할 때 main 메소드가 먼저로드됩니다. 그것 때문에static method. 그런 다음 그것은 객체로 보입니다."a" object그러나 아직 정의되지 않은 객체. 정적이 아니기 때문에. 그런 다음이 오류와 같이 실행하십시오.

연결된 질문


관련된 질문

최근 질문