정적 키워드

때때로 당신은 그 클래스의 다른 모든 객체와 독립적으로 사용될 클래스의 멤버를 정의하고 싶을 때가 있습니다. 일반적으로 클래스 멤버에 대한 액세스는 이 클래스의 개체를 통해 구성되지만 동시에 개체의 특정 인스턴스를 참조하지 않고 독립적으로 사용할 클래스 멤버를 생성하는 것도 가능합니다. 이러한 클래스 멤버를 생성하려면 선언 맨 처음에 표시하는 것으로 충분합니다. 예어공전.

클래스 멤버가 정적으로 선언되면 해당 클래스의 개체가 생성되기 전에 개체에 대한 참조 없이 사용할 수 있게 됩니다. static 키워드는 변수와 메서드를 모두 선언하는 데 사용할 수 있습니다. 정적 멤버의 가장 일반적인 예는 Main() 메서드이며 호출해야 하기 때문에 그렇게 선언됩니다. 운영 체제실행 중인 프로그램의 맨 처음에.

클래스 외부에서 정적 유형의 멤버를 사용하려면 이 클래스의 이름을 점 연산자로 지정하는 것으로 충분합니다. 하지만 이를 위해 객체를 생성할 필요는 없습니다. 사실, 정적 멤버는 개체에 대한 참조로 액세스할 수 없지만 해당 클래스의 이름으로 액세스할 수 있습니다.

static으로 선언된 변수는 본질적으로 전역적입니다. 객체가 클래스에서 선언되면 복사 유형 변수정적이 생성되지 않습니다. 대신 클래스의 모든 인스턴스는 정적 유형의 동일한 변수를 공유합니다. 이러한 변수는 클래스에서 사용되기 전에 초기화됩니다.

정적 키워드 사용의 예:

시스템 사용; System.Collections.Generic 사용; System.Linq를 사용하여; System.Text 사용; namespace ConsoleApplication1 ( class myCircle ( // 원의 면적과 길이를 반환하는 2개의 메서드 public static double SqrCircle(int radius) ( return Math.PI * 반경 * 반경; ) public static double LongCircle(int 반경) ( return 2 * Math.PI * radius; ) ) class Program ( static void Main(string args) ( int r = 10; // 이 클래스의 객체를 인스턴스화하지 않고 // 다른 클래스에서 메서드를 호출합니다. Console.WriteLine("Area of ​​​a 반지름이 (0)인 원 = (1 :#.##)",r,myCircle.SqrCircle(r)); Console.WriteLine("원의 길이는 (0:#.##)입니다.",myCircle. LongCircle(r)), Console.ReadLine(), ) ) )

정적 유형 메소드의 사용에는 여러 가지 제한이 있습니다.

    정적 유형의 메소드에는 이 참조가 없어야 합니다. 이러한 메소드는 어떤 객체에서도 실행되지 않기 때문입니다.

    정적 유형의 메소드에서는 동일한 클래스의 인스턴스 메소드가 아닌 정적 유형의 다른 메소드만 직접 호출할 수 있습니다. 요점은 인스턴스 메서드는 특정 개체에 대해 작동하고 정적 형식 메서드는 개체에 대해 호출되지 않는다는 것입니다. 따라서 이러한 메서드에는 작동할 수 있는 개체가 없습니다.

    정적 유형의 데이터에도 유사한 제한 사항이 적용됩니다. 정적 유형의 메소드의 경우 해당 클래스에 정의된 정적 유형의 다른 데이터에만 직접 액세스할 수 있습니다. 특히 그는 자신이 작업할 수 있는 개체가 없기 때문에 클래스의 인스턴스 변수에 대해 작업할 수 없습니다.

정적 생성자

생성자는 static으로 선언될 수도 있습니다. 정적 생성자는 일반적으로 해당 클래스 개체의 단일 인스턴스가 아니라 전체 클래스에 적용되는 구성 요소를 초기화하는 데 사용됩니다. 따라서 클래스 멤버는 해당 클래스의 개체가 생성되기 전에 정적 생성자로 초기화됩니다.

시스템 사용; System.Collections.Generic 사용; System.Linq를 사용하여; System.Text 사용; namespace ConsoleApplication1 ( class MyClass ( public static int a; public int b; // 정적 생성자 static MyClass() ( a = 10; ) // 일반 생성자 public MyClass() ( b = 12; ) ) class Program ( static void Main (문자열 인수) ( Console.WriteLine("클래스 a의 인스턴스에 액세스: " + MyClass.a); MyClass obj = new MyClass(); Console.WriteLine("클래스 b의 인스턴스에 액세스: " + obj.b) ; 콘솔 .ReadLine(); ) ) )

정적 유형 생성자는 클래스가 처음 로드될 때 인스턴스 생성자 이전에 자동으로 호출됩니다. 이것으로부터 우리는 보다 일반적인 결론을 도출할 수 있습니다. 정적 생성자는 인스턴스 생성자보다 먼저 실행되어야 합니다. 또한 정적 생성자는 액세스 수정자가 없습니다. 기본 액세스 권한이 있으므로 프로그램에서 호출할 수 없습니다.

정적 클래스

클래스는 static으로 선언할 수 있습니다. 정적 클래스에는 두 가지 주요 속성이 있습니다. 먼저 정적 클래스 개체를 만듭니다. 그것은 금지되어 있습니다. 둘째, 정적 클래스는 정적 멤버만 포함해야 합니다. static 키워드로 수정된 다음 클래스 선언 형식으로 정적 클래스가 생성됩니다.

정적 클래스 클래스 이름( // ...

정적 클래스는 주로 두 가지 경우에 사용됩니다. 첫째, 생성할 때 정적 클래스가 필요합니다. 확장 방법. 확장 메서드는 대부분 LINQ 언어와 연결되어 있습니다. 둘째, 정적 클래스는 서로 관련된 정적 메서드 모음을 저장하는 역할을 합니다.

이 기사에서는 Java의 정적 메소드를 탐색하고 정적 및 인스턴스를 비교합니다. 기억해야 할 주요 사항은 정적 키워드를 메서드와 함께 사용하는 경우 이를 정적 메서드라고 한다는 것입니다.

Java의 정적 메소드는 무엇입니까?

정적 메서드클래스의 객체를 생성하지 않고 호출할 수 있는 Java의 메소드입니다. 그것들은 이름(클래스 카테고리)으로 문서화됩니다.
static 키워드는 클래스, 변수, 메소드, 블록과 함께 사용할 수 있습니다. 정적 멤버특정 인스턴스가 아닌 클래스에 속하므로 멤버를 정적으로 만들면 객체 없이 액세스할 수 있습니다. 이를 이해하기 위해 예를 들어 보겠습니다.

여기에 정적 메서드 myMethod()가 있습니다. 멤버를 정적으로 만들면 클래스 수준이 되기 때문에 객체 없이 이 메서드를 호출할 수 있습니다. static 키워드를 제거하고 비정적 키워드로 만들면 이를 호출할 클래스 객체를 생성해야 합니다.

정적 멤버는 클래스의 모든 인스턴스(객체)에 공통되지만 비정적 멤버는 각 클래스 인스턴스에 대해 별도입니다.

Class SimpleStaticExample ( // 이것은 정적 메서드입니다. static void myMethod() ( System.out.println("myMethod"); ) public static void main(String args) ( /* 당신은 할 수 있습니다객체를 생성하지 않고 이 * 메소드를 호출하고 있음을 확인하십시오. */ myMethod(); ) )

통사론

public static void geek(String name) ( // 실행할 코드....

그것은 영구 세대에 저장되는데, 그 이유는 그것이 그 클래스의 객체가 아니라 그들이 있는 곳의 (범주 클래스)와 연관되기 때문입니다. 그러나 로컬 변수와 전달된 인수는 스택에 있습니다.

중요 사항:

  • 자신이 속한 클래스와 연결된 정적 메서드, 즉 클래스를 인스턴스화하지 않는 경우에도 참조합니다. 클래스 이름.메소드 이름(인수).
  • 그들은 다음을위한 것입니다 나누는동일한 클래스에서 생성된 모든 객체
  • 정적 메서드는 재정의할 수 없습니다.

Java에서 정적 메소드를 사용하는 예:

가져오기 java.io.*; class Flair( public static String FlairName = ""; public static void geek(String name) ( FlairName = name; ) ) class GFG ( public static void main (String args) ( Flair.flair("vaibhav"); System.out .println(Flair.flairName); Flair obj = new Flair(); obj.flair("shadow"); System.out.println(obj.flairName); ) )

결론:
바이바브
그림자

정적 변수(정적)와 그 값(기본 또는 참조)은 클래스 내부에 정의되어 PermGen 메모리 공간에 저장됩니다.

정적 변수가 객체를 참조한다면?

정적 정수 i = 1;
정적 개체 obj = 새 개체();

첫 번째 줄은 PermGen 섹션에 저장될 값입니다. 두 번째 줄에서 obj 참조는 PermGen 섹션에 저장되고 참조하는 개체는 힙 섹션에 저장됩니다.

언제 사용됩니까?

  • 동일한 클래스의 모든 인스턴스에서 공유할 수 있는 코드가 있는 경우 해당 코드를 Static 메서드에 넣습니다.
  • 먼저 클래스에 대한 정적 액세스 필드를 설정합니다.

Java 인스턴스 메소드란 무엇입니까?

자바 인스턴스 메소드클래스의 객체가 호출되기 전에 생성될 수 있는 방법입니다. 인스턴스 메소드를 호출하려면 정의된 범주에서 객체를 만들어야 합니다.

Public void flair(String name) // code to be (executed.... ) // 반환 유형은 int, float 문자열 또는 사용자 정의 데이터 유형일 수 있습니다.

매개변수(전달된 인수)와 해당 지역 변수 및 반환 값은 스택에 할당됩니다.

중요 사항:

  • 인스턴스는 클래스가 아닌 클래스 개체에 속합니다. 즉, 클래스 개체가 생성된 후에도 그대로 참조됩니다.
  • 별도의 개체(클래스, 카테고리)에서 생성된 A에는 해당 클래스의 인스턴스 메서드에 대한 자체 복사본이 있습니다.
  • 재정의할 수 있습니다.

Java의 인스턴스 메소드 또는 정적 메소드?

  • 인스턴스 메서드는 인스턴스 메서드 및 변수에 직접 액세스할 수 있습니다.
  • 인스턴스 메서드는 정적 변수와 정적 메서드에 직접 액세스합니다.
  • 정적 메서드는 정적 변수와 메서드에 직접 액세스합니다.
  • 정적 메서드는 인스턴스 메서드와 인스턴스 변수에 직접 액세스할 수 없습니다. 그리고 "this"가 참조할 인스턴스가 없기 때문에 정적 메서드는 이것을 사용할 수 없습니다.

그런 다음 클래스 이름 및 범위 확인 연산자를 통해 직접 액세스할 수 있습니다. 그러나 정적 멤버 변수가 비공개인 경우에는 어떻게 될까요? 다음 코드를 고려하십시오.

이 경우 멤버가 private이기 때문에 main()에서 Everything::s_value에 직접 액세스할 수 없습니다. 일반적으로 클래스의 private 멤버는 public 메서드를 통해 액세스합니다. s_value에 접근하기 위한 일반 메소드를 생성할 수 있지만, 그 메소드를 사용하려면 해당 클래스의 객체를 생성해야 합니다! 더 나은 옵션이 있습니다. 메서드를 정적으로 만들 수 있습니다.

정적 멤버 변수와 마찬가지로 정적 메서드하나의 클래스 객체에 묶여 있지 않습니다. 다음은 위의 예이지만 정적 메서드를 사용합니다.

class any ( private: static int s_value; public: static int getValue() ( return s_value; ) // 정적 메서드 ); 정수::s_value = 3; // 정적 멤버 변수 정의 int main() ( std::cout<< Anything::getValue() << "\n"; }

정적 메서드는 특정 개체에 바인딩되지 않기 때문에 클래스 이름 및 범위 확인 연산자를 통해 또는 클래스 개체를 통해 직접 호출할 수 있습니다(그러나 권장하지 않음).

정적 메서드에는 *this 포인터가 없습니다.

정적 메서드에는 두 가지 흥미로운 기능이 있습니다. 첫째, 정적 메서드는 객체에 바인딩되지 않기 때문에 ! 이것은 *this 포인터가 항상 메서드가 작업 중인 개체를 가리키기 때문에 의미가 있습니다. 정적 메서드는 개체를 통해 작동하지 않을 수 있으므로 *this 포인터가 필요하지 않습니다.

둘째, 정적 메서드는 다른 정적 멤버(변수 또는 함수)에 직접 액세스할 수 있지만 비정적 멤버에는 액세스할 수 없습니다. 비정적 멤버는 클래스 개체에 속하지만 정적 메서드는 그렇지 않기 때문입니다!

한 가지 더 예

정적 메서드는 클래스 본문 외부에서 정의할 수 있습니다. 이것은 일반적인 방법과 동일한 방식으로 작동합니다. 예를 들어:

#포함 class IDGenerator ( private: static int s_nextID; // 정적 멤버 변수 선언 public: static int getNextID(); // 정적 메서드 선언 ); // 정적 멤버 변수의 정의는 클래스 본문 외부에 있습니다. 여기서 static 키워드를 사용하지 않음을 주목하세요. // Start ID generation at 1 int IDGenerator::s_nextID = 1; // 정적 메서드 정의는 클래스 본문 외부에 있습니다. 여기서 정적 int IDGenerator::getNextID() ( return s_nextID++; ) 키워드를 사용하지 않는다는 점에 유의하십시오. int main() ( for (int count=0; count< 4; ++count) std::cout << "The next ID is: " << IDGenerator::getNextID() << "\n"; return 0; }

#포함

classID 생성기

사적인 :

정적 int s_nextID ; // 정적 멤버 변수 선언

공공의 :

정적 정수 getNextID(); // 정적 메소드 선언

// 1부터 ID 생성 시작

int IDGenerator :: s_nextID = 1 ;

int IDGenerator :: getNextID() ( s_nextID ++ 반환 ; )

정수 메인()

for (int count = 0 ; count< 4 ; ++ count )

표준::컷<< "The next ID is: " << IDGenerator :: getNextID () << "\n" ;

0 반환 ;

위 프로그램을 실행한 결과는 다음과 같습니다.

다음 ID는 1입니다.
다음 ID는 2입니다.
다음 ID는 3입니다.
다음 ID는 4입니다.

이 클래스의 모든 변수와 함수는 정적이므로 작업하기 위해 이 클래스의 개체를 만들 필요가 없습니다! 정적 멤버 변수는 할당할 다음 식별자의 값을 저장하는 데 사용되며 정적 메서드는 식별자를 반환하고 증가시키는 데 사용됩니다.

모든 정적 멤버가 있는 클래스에 대한 경고

모든 정적 멤버로 클래스를 작성할 때는 주의하십시오. 이러한 "순수한 정적 클래스"는 유용할 수 있지만 단점도 있습니다.

첫째, 모든 정적 멤버는 한 번만 생성되기 때문에 "순전히 정적 클래스"의 복사본이 여러 개 있을 수 없습니다(클래스를 복제하고 나중에 이름을 바꾸지 않고). 예를 들어, IDGenerator 클래스의 두 개의 독립적인 객체가 필요한 경우 "순전히 정적" 클래스를 통해 이는 불가능합니다.

C++는 정적 생성자를 지원하지 않습니다.

를 통해 일반 멤버 변수를 초기화할 수 있다면 논리적으로 정적 생성자를 통해 정적 멤버 변수를 초기화할 수 있어야 합니다. 그리고 일부 현대 언어는 정확히 이 목적을 위해 정적 생성자를 지원하지만 불행히도 C++는 그 중 하나가 아닙니다.

정적 변수를 직접 초기화할 수 있는 경우 생성자가 필요하지 않습니다. 정적 멤버 변수가 개인용인 경우에도 정의할 수 있습니다. 위의 예에서 s_nextID를 사용하여 이 작업을 수행합니다. 다음은 또 다른 예입니다.

클래스 뭔가 ( public: static std::vector s_mychars; ); 표준::벡터 뭔가::s_mychars = ( "o", "a", "u", "i", "e" ); // 정적 멤버 변수 정의

classSomething

공공의 :

정적 표준 :: 벡터< char >s_mychars ;

표준::벡터< char >뭔가 :: s_mychars = ( "o" , "a" , "u" , "i" , "e" ) ; // 정적 멤버 변수 정의

정적 멤버 변수를 초기화할 때 코드(예: 루프)를 실행해야 하는 경우 여러 가지 방법이 있습니다. 다음 방법이 가장 좋습니다.

#포함 #포함 클래스 뭔가 ( private: static std::vector s_mychars; public: class _nested // _nested라는 중첩 클래스를 정의합니다( public: _nested() // _nested 생성자는 정적 멤버 변수를 초기화합니다( s_mychars.push_back("o"); s_mychars.push_back("a"); s_mychars.push_back( "u"); s_mychars.push_back("i"); s_mychars.push_back("e"); ) ); // s_mychars를 출력하기 위한 정적 메소드 static void getSomething() ( for (auto const &element: s_mychars) std::cout<< element << " "; } private: static _nested s_initializer; // используем статический объект класса _nested для гарантии того, что конструктор _nested выполнится }; std::vector뭔가::s_mychars; // 정적 멤버 변수 정의 Something::_nested Something::s_initializer; // s_mychars를 초기화하기 위해 _nested 생성자를 호출하는 정적 s_initializer를 정의합니다. int main() ( Something::getSomething(); return 0; )

#포함

#포함

classSomething

사적인 :

정적 표준 :: 벡터< char >s_mychars ;

공공의 :

class_nested // _nested라는 중첩 클래스를 정의합니다.

공공의 :

중첩() // _nested 생성자는 정적 멤버 변수를 초기화합니다.

s_mychars . push_back("o") ;

s_mychars . push_back("a") ;

s_mychars . push_back("u") ;

s_mychars . push_back("i") ;

s_mychars . push_back("e") ;

대부분의 C++ 키워드를 사용하면 한 가지 작업을 수행할 수 있습니다. int를 사용하여 정수 변수를 선언하거나 함수가 정수 값을 반환하거나 정수를 인수로 사용할 때 사용합니다. new 연산자를 사용하여 메모리를 할당하고 delete 연산자를 사용하여 메모리를 해제합니다. const를 사용하여 변수 값을 변경할 수 없음을 나타낼 수 있습니다. 아이러니하게도 static 키워드는 "변하지 않는"을 의미하지만 여러 가지(그리고 분명히 관련이 없는) 용도를 가지고 있습니다. static 키워드는 세 가지 주요 컨텍스트에서 사용할 수 있습니다.

  • 함수 내부;
  • 클래스 정의 내부;
  • 다중 파일 프로그램을 구성하는 파일 내 전역 변수 앞에

함수 내에서 static을 사용하는 것이 가장 쉽습니다. 단순히 변수가 초기화된 후 프로그램이 끝날 때까지 메모리에 남아 있음을 의미합니다. 프로그램이 끝날 때까지 값을 유지하는 변수로 생각할 수 있습니다. 예를 들어, 정적 변수를 사용하여 단순히 다음 행을 추가하여 함수가 호출된 횟수를 기록할 수 있습니다. static int count = 0; 그리고 카운트++; 기능으로. count는 정적 변수이므로 line static int count = 0; 한 번만 실행됩니다. 함수가 호출될 때마다 count는 마지막 값을 갖게 됩니다.

이 방법으로 static을 사용하여 루프 내에서 변수가 다시 초기화되는 것을 방지할 수도 있습니다. 예를 들어, 다음 코드에서 number_of_times 변수는 100과 같습니다. static int number_of_times = 0; 프로그램이 루프에 도달할 때마다 실행되어야 하는 루프 내부에 있습니다. 트릭은 static 키워드가 변수가 다시 초기화되는 것을 방지한다는 것입니다. static 키워드를 사용하는 방법 중 하나는 자동으로 변수를 0으로 설정한다는 것입니다. 그러나 그것에 의존하지 마십시오(의도를 불분명하게 만듭니다).

For(int ix=0; ix< 10; ix++) { for(int iy = 0; iy < 10; iy++) { static int number_of_times = 0; number_of_times++; } }

예를 들어 함수에서 계산된 최대값을 저장하려는 경우 정적 변수를 사용하여 반환된 함수의 마지막 값에 대한 정보를 저장할 수 있습니다. 문자열을 구문 분석하는 경우 마지막 문자를 반환해야 함을 나타내는 인수를 사용하여 호출할 수 있도록 함수에서 반환된 마지막 문자를 저장할 수도 있습니다.

static의 두 번째 용도는 클래스 정의 내에서입니다. 클래스 내에서 선언된 대부분의 변수는 클래스의 각 인스턴스에서 다른 값을 가질 수 있지만 클래스의 정적 필드는 해당 클래스의 모든 인스턴스에 대해 동일한 값을 가지며 해당 클래스의 인스턴스를 만들 필요조차 없습니다. . 정적 클래스 변수를 새 개체를 만드는 데 필요한 정보를 보유하는 것으로 생각하는 것이 유용합니다(예: 클래스 팩토리에서). 예를 들어 클래스의 인스턴스에 번호를 지정하려는 경우 정적 변수를 사용하여 마지막으로 사용된 번호를 추적할 수 있습니다. 정적 클래스 변수를 사용하여 class_name::x; , instance_of_class.x가 아닙니다. . 이것은 정적 변수가 동일한 클래스 인스턴스에 속하지 않으며 해당 클래스의 인스턴스를 만들 필요가 없다는 것을 프로그래머에게 상기시키는 데 도움이 됩니다. 지금쯤이면 눈치채셨겠지만 클래스 이름을 통해 static에 액세스할 때 범위 연산자 :: 를 사용하여 static에 액세스할 수 있습니다.

static 을 사용하여 프로그램을 디버깅하거나 구현할 때 클래스 내에서 초기화할 수 없다는 점을 명심하는 것이 중요합니다. 실제로 헤더 파일에 모든 클래스 코드를 작성하기로 결정했다면 헤더 파일 내부에서 정적 변수를 초기화할 수도 없습니다. .cpp 파일에서 수행하십시오. 또한 클래스의 정적 멤버를 초기화해야 합니다. 그렇지 않으면 해당 멤버가 범위에 포함되지 않습니다. (구문은 약간 이상합니다: type class_name::static_variable = value .)

정적 클래스 함수를 가질 수도 있습니다. 정적 함수는 클래스의 인스턴스가 필요하지 않으며 정적 변수와 유사한 방식으로 개체 이름이 아닌 클래스 이름으로 같은 방식으로 호출되는 함수입니다. 예를 들어, a_class::static_function(); , an_instance.function()이 아닙니다. . 정적 함수는 클래스의 특정 인스턴스를 참조하지 않기 때문에 클래스의 정적 멤버에서만 작동할 수 있습니다. 정적 함수는 정적 변수를 변경하고 값을 추적하는 데 사용할 수 있습니다. 예를 들어 카운터를 사용하여 각 클래스 인스턴스에 고유 식별자를 부여하기로 결정한 경우 정적 함수를 사용할 수 있습니다.

예를 들어 다음 코드를 사용할 수 있습니다.

클래스 user ( private: int id; static int next_id; public: static int next_user_id() ( next_id++; return next_id; ) // 사용자 클래스의 다른 메소드 user() // 클래스 생성자( id = user::next_id++; / / 또는 메소드 호출, id = user.next_user_id(); ) ); int 사용자::next_id = 0;

설정할 때 정적 변수의 유형을 포함해야 합니다!

사용자 a_user;

다른 사용자 개체가 사용하지 않는 다음 ID 번호로 ID를 설정합니다. 식별자를 상수로 선언하는 것이 좋은 스타일입니다.

static의 마지막 사용은 코드 파일의 전역 변수입니다. 이 경우 정적 사용은 프로젝트의 일부인 다른 파일의 소스 코드가 변수에 액세스할 수 없음을 나타냅니다. 동일한 파일 내의 코드만 변수를 볼 수 있습니다(범위는 파일로 제한됨). 이 기술은 변수의 가시성을 제한하고 이름 충돌을 방지하는 데 도움이 되기 때문에 객체 지향 코드를 모델링하는 데 사용할 수 있습니다. static을 사용하는 이 방법은 C에서 계승된 것입니다.