Java의 전역 변수


217

Java에서 전역 변수를 어떻게 정의합니까?


20
Java로 전역 변수를 정의하려는 이유 를 알려주 시겠습니까?
Adam Paynter

44
클래스 외부에서 변수에 액세스하려면
aTJ

5
아마도 원하는 것을 정확하게 보여주는 샘플 코드를 포함하도록 질문을 편집해야 할 것입니다. 최상의 솔루션을 추천하는 데 도움이 될 것입니다.
Adam Paynter

7
@Adam : 한 클래스의 변수 값을 다른 클래스에서 변경할 수 있어야합니다.
aTJ

2
당신은하지 않습니다. Java에는 전역 변수가 없습니다.
Lorne의 후작

답변:


261

전역 변수를 정의하기 위해 정적 키워드를 사용할 수 있습니다

public class Example {
    public static int a;
    public static int b;
}

지금 당신은 전화로 어디서나 a와 b에 액세스 할 수 있습니다

Example.a;

Example.b;

6
"Global"은 클래스 이름입니다.
Jerome

12
글로벌 클래스가 언로드 될 때 변수는 정의되지 않은 null이됩니다. 당신이 당신의 응용 프로그램을 판매하는 경우 이것은 조만간 발생하고 당신은 어디에서나 오류를 계속 찾고 있지만 ....
user387184

10
static자신의 클래스가로드되는 동안 키워드, 변수는 전역 적으로 액세스 할 수 있습니다.
sjas

22
클래스 언로드 정보 : GC Root에서 Global 또는 그 하위 인스턴스로의 강력한 참조 체인이 있거나로드 및 언로드 할 수없는 클래스에서 Global 로의 컴파일 타임 참조가있는 경우 Global과 관련된 Class 객체는 강력합니다 도달 가능하므로 Global을로드 한 ClassLoader도 마찬가지입니다. 클래스 언로드는 GC가 주어진 클래스를로드 한 ClassLoader에 대한 강력한 참조를 완전히 제거한 후에 만 ​​발생할 수 있기 때문에 글로벌 언로드가 불가능합니다. 전혀 참조가 없다면 언로드가 어떻게 문제가 될 수 있습니까 ???
Bruno Reis

4
@Abi 사람들에게 Java 키워드 와 같은 것이 있다는 인상을주지 않기 위해 클래스 이름 Global을 다른 ( TestClass?)로 바꾸는 것이 좋습니다 Global. 죄송합니다보다 안전합니다 :)
Nicolas

53

당신은하지 않습니다. 의도적으로 설계된 것입니다. 할 수 있어도하지 말아야합니다.

즉, Globals라는 클래스에 공개 정적 멤버 세트를 작성할 수 있다고합니다.

public class Globals {
   public static int globalInt = 0;
   ///
}

그러나 당신은 정말로해서는 안됩니다 :). 진심으로 ..하지 마십시오.


6
그렇다면 모든 클래스 메소드가 액세스 할 수 있도록 상수를 선언 할 수있는 더 좋은 방법은 무엇입니까?
Alston

6
이런 성격의 글은 초보자가 전역 변수 공포증을 발전시키는 이유이며, 그런 다음 전역 변수 금기를 회피하기 위해 모든 종류의 엄청나게 많은 기술이 고 안되지만 동일한 효과를 달성합니다.
Evgeni Sergeev

40
"하지 마라"고 투표하십시오. 이유를 설명하거나 언급하지 않고.
Jeff McCune 2016 년

4
@JeffMcCune : 당신의 진술을보다 명확하게하기 위해, "하지 마십시오"는 실제로 헛소리입니다. 유용 할 때하십시오. 예를 들어, 일부 IAbstractLoggerBullshit을 사용하여 코드를 디버깅해야하며이 과도하게 엔지니어링 된 환경에서는 System.err가 작동하지 않습니다. 수백 개의 쓸모없는 어댑터 클래스 사이에서 로거 크랩을 통과하는 코드를 버릴 수 없습니다.
Jo So

6
내가 할거야.
떠 다니는 선 피쉬

40

다른 방법은 다음과 같은 인터페이스를 만드는 것입니다.

public interface GlobalConstants
{
  String name = "Chilly Billy";
  String address = "10 Chicken head Lane";
}

그것들을 사용해야하는 모든 클래스는 인터페이스를 구현해야합니다.

public class GlobalImpl implements GlobalConstants
{
  public GlobalImpl()
  {
     System.out.println(name);
  }
}

이 답변에 왜 내 투표가 없는지 궁금합니다. 다른 모든 답변에서 제공하는 답변에 대해 합리적인 대안 답변을 제공하지 않습니까?
M_M

12
Joshua Bloch의 효과적인 Java, 제 4 장 : 클래스 및 인터페이스, 항목 19 : 인터페이스 만 사용하여 유형을 정의하십시오. "상수 인터페이스 패턴은 인터페이스를 잘 사용하지 않습니다." 이 책은 읽을 가치가 있습니다! :)
MariuszS

1
또한 JDK 1.5 이상에서는 전역 변수에 정적 가져 오기를 사용할 수 있으므로 구현할 필요가 없습니다.
MariuszS

9
.... 맞습니다. 실제로 어떤 것도 설명하지 않고 단지 어떤 책이 잘못되었다고 말합니다.
linkhyrule5

14
여기 인용문이 있습니다. 오라클은 "이 문제를 해결하기 위해 사람들은 때때로 정적 멤버를 인터페이스에 넣고 해당 인터페이스에서 상속합니다. 이것은 나쁜 생각입니다. 사실, 이름이 있다는 것은 나쁜 생각입니다. Constant Interface Antipattern (유효한 Java 항목 17 참조) 문제는 클래스가 다른 클래스의 정적 멤버를 사용하는 것이 단순한 구현 세부 사항이라는 점입니다. 클래스가 인터페이스를 구현할 때 클래스가 공용 API의 일부가됩니다. 공개 API. "
Jolta

23

의존성 주입을 사용하는 것이 좋습니다.

public class Globals {
    public int a;
    public int b;
}

public class UsesGlobals {
    private final Globals globals;
    public UsesGlobals(Globals globals) {
        this.globals = globals;
    }
}

5
"글로벌"을 사용하면 상황이 약간 혼동된다고 생각합니다. "매개 변수"와 같은 것이 반드시 글로벌 일 필요는 없기 때문에 더 적합 할 것입니다.
Mark Peters

12

좋은 대답이 많이 있지만 다른 클래스가 클래스의 변수에 액세스하는 더 적절한 방법 인 getter 및 setter를 사용하는 것으로 간주 되므로이 예제를 제공하고 싶습니다.

변수를 공용으로 만드는 대신 게터와 세터를 사용하는 이유는 다음과 같습니다. var가 전역 매개 변수가되어 프로그램을 실행하는 동안 (팀과 코드를 개발하는 경우) 누군가 웹 사이트의 URL과 같이 변경하지 않기를 바랍니다. 이론적으로 이것은 변경 될 수 있으며 프로그램에서 여러 번 사용될 수 있으므로 전역 변수를 사용하여 한 번에 모두 업데이트 할 수 있기를 원합니다. 그러나 다른 누군가가 들어가서이 var를 변경하는 것을 원하지 않습니다 (아마도 그것이 중요하지 않은지도 모릅니다). 이 경우 단순히 setter 메소드를 포함하지 않고 getter 메소드 만 포함하십시오.

public class Global{
    private static int var = 5;

    public static int getVar(){
        return Global.var;
    }

    //If you do not want to change the var ever then do not include this
    public static void setVar(int var){
        Global.var = var;
    }
}

10

Java에는 전역 변수가 없습니다

그럼에도 불구하고 우리가 가진 것은 static키워드이며 우리가 필요한 전부입니다. Java에서는 클래스 외부에 존재하는 것이 없습니다. 그만큼static키워드는 인스턴스 변수는 반대로, 하나의 복사본 만 그 값이 어느 시점에서 모든 인스턴스에 변경 및 액세스 할 수 있음을 의미 만든 그 클래스의 모든 인스턴스에 걸쳐 그 초월을 가지고있는 클래스 변수를 나타냅니다.

범위를 넘어 액세스 할 수있는 전역 변수가 필요한 경우 필요한 변수이지만 범위는 클래스가있는 위치에만 존재하며 이것이 전부입니다.


9

실제로 Java OO 프로그램 에는 "GLOBAL" 이라는 개념이 없다

그럼에도 불구하고 프로그램의 어느 부분에서나 메소드를 실행하려는 경우가 있기 때문에 질문 뒤에 약간의 진실이 있습니다. 예를 들어 Phrase-O-Matic 앱의 --random () 메소드는 프로그램의 어느 곳에서나 호출 할 수있는 메소드입니다.

위와 같은 것을 만족시키기 위해서는 "전역과 같은 변수와 방법이 필요합니다"

글로벌 변수로 선언합니다.

 1.Mark the variable as public static final While declaring.

글로벌 한 방법을 선언 합니다.

 1. Mark the method as public static While declaring.

전역 변수와 메소드를 정적으로 선언했기 때문에 다음 코드를 사용하여 원하는 곳 어디에서나 호출 할 수 있습니다

ClassName.X

참고 : X는 요구 사항에 따라 메서드 이름 또는 변수 이름이 될 수 있으며 ClassName은 선언 한 클래스의 이름입니다.


9

상수를 제외하고는 전역이 될 수 없습니다.

public class MyMainClass {
    public final static boolean DEBUGMODE=true;
}

이것을 메인 클래스에 넣으십시오. 다른 .java 파일에서는 다음을 통해 사용하십시오.

if(MyMainClass.DEBUGMODE) System.out.println("Some debugging info");

절단 실 바닥에서 코드를 옮길 때 릴리스 할 때이 기능을 제거하거나 주석 처리하십시오.

randomizer와 같은 주요 방법이 있다면 "Toolbox"패키지를 만드는 것이 좋습니다! 모든 코더에는 하나가 있어야하며, .java에서 사용할 때마다 가져 오십시오!


5

Java에는 진정한 전역 변수와 같은 것은 없습니다. 모든 정적 변수는 System.out과 같은 일부 클래스에 속해야하지만 어떤 클래스로 들어갈 지 결정하면 동일한 클래스 로더가로드 한 모든 곳에서 변수를 참조 할 수 있습니다.

경쟁 조건을 피하기 위해 업데이트 할 때는 정적 변수를 항상 보호해야합니다.


1
java는 기능적으로 전역 변수를 제공하지 않지만 전역 변수 개념을 원한다면 정적 키워드를 사용할 수 있습니다.
Abi

3
public class GlobalClass {
     public static int x = 37;
     public static String s = "aaa";
}

당신이 액세스 할 수 있습니다이 방법 GlobalClass.xGlobalClass.s


2
public class GlobalImpl {   

 public static int global = 5;

}

원하는 곳 어디든 전화 할 수 있습니다.

GlobalImpl.global // 5

1

아마도 대답에서 짐작할 수 있듯이 Java에는 전역 변수가 없으며 정적 멤버로 클래스를 만드는 것만 가능합니다.

public class Global {
    public static int a;
}

Global.a다른 곳에서 사용할 수 있습니다 . 그러나 Java 1.5 이상을 사용하는 경우 import static마술을 사용하여 실제 전역 변수처럼 보이게 할 수 있습니다 .

import static test.Global.*;

public class UseGlobal {
    public void foo() {
        int i = a;
    }
}

그리고 il !

이제는 광고에서 볼 수 있듯이 모범 사례와는 거리가 멀 습니다. 집에서하지 마십시오.


1

Java에는 전역 변수가 없지만 공용 필드가있는 전역 클래스가 있습니다. java 5의 정적 가져 오기 기능을 사용하여 거의 전역 변수처럼 보이게 할 수 있습니다.


1

일반적으로 전역 변수 (C, Cpp와 비교한다고 가정)는 다음과 같이 정의합니다. public static final

처럼

class GlobalConstant{
    public static final String CODE  = "cd";
}

ENUM은 다음과 같은 시나리오에서도 유용합니다.

예를 들어 Calendar.JANUARY)


전역 변수가 최종이어야합니까? 왜?
Konerak

1
"final"은 "constant"를 의미하므로 전역 상수입니다.
duffymo

1
아니, 그 변수를 공유하고 데이터를 변경하려는 경우 전역 변수가 의미하는 바는 그냥 제거 final하지만 확실히 공유하려는 방법, 사용하는 위치 및 모두
Jigar Joshi

CODE이 예에서 유형은 무엇입니까 ? 어디에 정의되어 있습니까?
M_M

또한 참고 : CODE는 모든 대문자로 표시됩니다. 최종으로 선언 한 변수에 대해 모든 대문자를 사용하고 프로그램 과정에서 변경하지 않으려는 일반적인 Java 표기법입니다.
Dan Ciborowski-MSFT

1

독립 파일 작성 (예 : 첫 번째 솔루션을 사용하는 Example.java는 괜찮습니다. 전역 변수가 현재 앱에 특수한 경우 등 앱 내에서도이를 수행 할 수 있습니다.

처음에 클래스를 만들고 거기에 변수를 선언하십시오.

class Globals {
  static int month_number;
  static String month_name;
}

그런 다음 앱 어디에서나 'Globals.month_number'등으로 변수에 액세스 할 수 있습니다.


downvoting 대신이 솔루션에 어떤 문제가 있는지 말씀해 주시겠습니까? 나는 그것을 지속적으로 사용하고 있으며 가장 편리합니다. 그래서 나는이 다운 보트를 개인적인 것으로 생각하거나 어리석은 사람에 의해 행해지는 것을 달리 할 수 ​​없습니다.
Apostolos

1

전역 속성을 업데이트해야하는 경우 간단한 getter / setter 래퍼 클래스를 전역 변수로 사용할 수 있습니다. 일반적인 예는 다음과 같습니다.

public class GlobalHolder {

    private static final GlobalHolder INSTANCE = new GlobalHolder();

    private volatile int globalProperty;

    public static GlobalHolder getInstance() {
        return INSTANCE;
    }

    public int getGlobalProperty() {
        return globalProperty;
    }

    public void setGlobalProperty(int globalProperty) {
        this.globalProperty = globalProperty;
    }

    public static void main(String[] args) {
        GlobalHolder.getInstance().setGlobalProperty(10);
        System.out.println(GlobalHolder.getInstance().getGlobalProperty());
    }
}

0

개념에 따라 인스턴스 변수라고도하는 전역 변수는 클래스 수준 변수입니다. 즉, 클래스 내부에서는 정의되지만 메서드 외부에서는 정의됩니다. 그것들을 완전히 사용 가능하게하고 그것들을 직접 사용하려면 static 키워드를 제공하십시오. 따라서 간단한 산술 연산을 위해 프로그램을 작성하고 숫자 쌍이 필요한 경우 두 개의 인스턴스 변수가 다음과 같이 정의됩니다.

public class Add {
    static int a;
    static int b; 
    static int c;

    public static void main(String arg[]) {
        c=sum();
        System.out.println("Sum is: "+c); 
    }

    static int sum() {
       a=20;
       b=30;
       return a+b;   
    }
}

Output: Sum is: 50

또한 인스턴스 변수 앞에 정적 키워드를 사용하면 동일한 변수에 대한 데이터 유형을 반복해서 지정할 수 없습니다. 변수를 직접 작성하십시오.


1
Java에는 전역 변수가 없습니다. 그것들은 인스턴스 변수로도 알려져 있지 않습니다. 그것들을 static'완전히 이용 가능하게'하지 않는 것으로 정의하십시오 . 첫 번째 단락은 말이되지 않습니다. 실례는 좋지 않습니다.
Lorne의 후작

0

일반적으로 Java에는 전역 변수가 없습니다. 지역 변수 이외의 모든 변수는 프로그램에 정의 된 모든 클래스의 범위에 속합니다. 전역 변수의 범위를 가지기 위해 정적 변수를 가질 수 있습니다.


0

이것 없이도 static가능합니다 :

class Main {
  String globalVar = "Global Value";

  class Class1 {
    Class1() {
      System.out.println("Class1: "+globalVar);
      globalVar += " - changed";
  } }
  class Class2 {
    Class2() {
      System.out.println("Class2: "+globalVar);
  } }

  public static void main(String[] args) {  
    Main m = new Main();
    m.mainCode();
  }
  void mainCode() {
    Class1 o1 = new Class1();
    Class2 o2 = new Class2();
  }
}

/*
Output:
Class1: Global Value
Class2: Global Value - changed
*/

0

객체 지향 프로그래밍 은 변수의 범위가 해당 변수를 캡슐화하는 클래스 객체와 밀접하게 배타적이라는 이해를 바탕으로 구축되었습니다.

"전역 변수"를 생성 할 때의 문제점은 Java의 산업 표준이 아니라는 것입니다. 다중 스레드 응용 프로그램을 실행하는 경우 여러 클래스가 비 동기화 된 데이터를 조작 할 수 있기 때문에 업계 표준이 아닙니다. 스레드 안전성 측면에서 좀 더 복잡하고 위험합니다. 가 있습니다 여러 가지 다른 이유로 사용하여 전역 변수가 비효율적 인 이유는,하지만 당신은이를 방지하려면, 난 당신에 의존 제안 가로 지향 프로그래밍 .

Aspect-Oriented Programming 은 "advices"라는 것을 통해 스코프를 담당하는 상위 클래스를 배치함으로써이 문제를 무효화합니다.이 클래스는 실제로 코드를 수정하지 않고 추가 동작을 추가합니다. 교차 절단 문제 또는 전역 변수 사용에 대한 솔루션을 제공합니다.

Spring 은 AOP를 사용하는 Java 프레임 워크이며 전통적으로 웹 애플리케이션에 사용되지만 핵심 애플리케이션은 Java 프레임 워크 (8.0 포함) 전체에서 보편적으로 사용할 수 있습니다. 이것은 더 탐구하고 싶은 방향 일 수 있습니다.


0

문제 이해

정적 / 인스턴스 호출을 신경 쓰거나 한 클래스에서 다른 클래스로 참조를 전달하지 않고 코드의 어느 곳에서나 액세스하고 변경할 수있는 변수전역 변수 의 자격을 고려합니다 .

보통 클래스 A가 있다면

public class A {
    private int myVar;

    public A(int myVar) {
        this.myVar = myVar;
    }

    public int getMyVar() {
        return myVar;
    }

    public void setMyVar(int mewVar) {
        this.myVar = newVar;
    }
}

myvar클래스 B에서 액세스하고 업데이트하려고합니다 .

public class B{

    private A a;

    public void passA(A a){
        this.a = a;
    }

    public void changeMyVar(int newVar){
        a.setMyvar(newVar);
    }
}

클래스 A의 인스턴스에 대한 참조가 있어야하고 다음과 같이 클래스 B의 값을 업데이트해야합니다.

int initialValue = 2;
int newValue = 3;
A a = new A(initialValue);
B b = new B();
b.passA(a);
b.changeMyVar(newValue);
assertEquals(a.getMyVar(),newValue); // true

해결책

따라서 이것에 대한 나의 해결책은 (좋은 습관인지 확실하지 않더라도) 싱글 톤을 사용하는 것입니다.


public class Globals {
    private static Globals globalsInstance = new Globals();

    public static Globals getInstance() {
        return globalsInstance;
    }

    private int myVar = 2;

    private Globals() {
    }

    public int getMyVar() {
        return myVar;
    }

    public void setMyVar(int myVar) {
        this.myVar = myVar;
    }
}

이제 다음을 통해 어디서나 글로벌 고유 인스턴스를 얻을 수 있습니다.

Globals globals = Globals.getInstance();
// and read and write to myVar with the getter and setter like 
int myVar = globals.getMyVar();
global.setMyVar(3);

-1
// Get the access of global while retaining priveleges.
// You can access variables in one class from another, with provisions.
// The primitive must be protected or no modifier (seen in example).

// the first class
public class farm{

  int eggs; // an integer to be set by constructor
  fox afox; // declaration of a fox object

  // the constructor inits
  farm(){
    eggs = 4;
    afox = new fox(); // an instance of a fox object

    // show count of eggs before the fox arrives
    System.out.println("Count of eggs before: " + eggs);

    // call class fox, afox method, pass myFarm as a reference
    afox.stealEgg(this);

    // show the farm class, myFarm, primitive value
    System.out.println("Count of eggs after : " + eggs);

  } // end constructor

  public static void main(String[] args){

    // instance of a farm class object
    farm myFarm = new farm();

  }; // end main

} // end class

// the second class
public class fox{

  // theFarm is the myFarm object instance
  // any public, protected, or "no modifier" variable is accessible
  void stealEgg(farm theFarm){ --theFarm.eggs; }

} // end class

2
이 답변은 다른 답변이하지 않는 것을 추가합니까? 이 답변에서 "새로운"값을 볼 수 없습니다.
EWit

-2

전역 변수를 정의하기 위해 정적 키워드를 사용할 수 있습니다

public final class Tools {
  public static int a;
  public static int b;
}

지금 당신은 전화로 어디서나 a와 b에 액세스 할 수 있습니다

Tools.a;
Tools.b;

Yoy 맞습니다 ... 특히 J2ME에서 ...이 코드 줄에 MidLet 생성자 (프로기 초기화)를 넣음으로써 NullPointerException을 피할 수 있습니다.

new Tools();

이렇게하면 도구를 사용하는 명령 전에 도구가 할당됩니다.

그게 다야!


3
음 ... 죄송합니다. 기존 답변에서 아직 다루지 않은 추가 기능은 무엇입니까?
신비주의

아마도 당신 말이 맞을 것입니다 ..하지만이 답변은 메모리 할당과 같은 것을 설명합니다.
user2616742

Java에는 정적 최상위 클래스가 없습니다.
Andremoniy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.