Java의 static이라면

18073 단어 Java

개시하다


이 글은 MicroAd Advent Calendar 2017 18일째 되는 글이다.
평소에 그걸 깨달았는지.
지금 말하지 않으면 앞으로 할 말이 없겠지. 난 자바에서 static의 현황을 말하고 싶어.

골대


그냥 static이지만 static,
간단한 수수께끼를 쓰면서 자바의 static 물건을 슬그머니 정리한다.

static 필드


원래 static은'정적'이라는 뜻이다.살금살금
동적이지 않기 때문에 많은 실례가 생겨도 한 반에 불과하다.
여러 실례 사이에서 공유된 정보와 자원을 공유하고자 하는 필드에static을 추가합니다.호칭.실례를 만들고 호출해도 같은 파일에 접근할 수 있습니다.
상수를 정의할 때クラス名.フィールド名 설명하면 업데이트할 때마다 같은 값이 실례로 복사되는 것을 방지하고 메모리를 절약하는 데 도움이 된다.
public final static String KEY = "happy-toilet";
어디서든 불러낼 수 있는 즐거운 화장실의 고정값이다.

static 방법(클래스 방법)


static 방법 자체는 클래스 실례에 속하지 않고 클래스에 속한다.
호출final static, 함수형 인터페이스의 방법 참조 시クラス名.メソッド名는 직접 호출할 수 있습니다.
static 필드와 함께 정적 구성원이라고 합니다.
static이 없는 일반적인 방법을 비static방법, 실례방법이라고 한다.
다음은java8 이후 함수 인터페이스 방법 인용 중static 방법과 실례 방법 호출의 차이입니다.
MethodReference.java
public class MethodReference {

  public static void main(String[] args) {
    // static メソッド
    wakeUp(MethodReference::printWakeUp);

    System.out.print(" and ");

    // インスタンスメソッド
    MethodReference mr = new MethodReference();
    mr.goToilet(mr::printGoToilet);
  }

  interface Human {
    void doSomething();
  }

  static void wakeUp(Human human) {
    human.doSomething();
  }

  static void printWakeUp() {
    String wakeUp = "wake up";
    System.out.print(wakeUp);
  }

  void goToilet(Human human) {
    human.doSomething();
  }

  void printGoToilet() {
    String toilet = "happy toilet";
    System.out.print(toilet);
  }
}
결과는 wake up and happy toilet입니다.

덮어쓸 수 없음

public class StaticPractice {

  public static void main(String[] args) {

    Human developer = new Developer();

    System.out.println(developer.getMorning());

  }
}

class Human {
  static String morning = "Happy Toilet";

  static String getMorning() {
    return morning;
  }
}

class Developer extends Human {
  static String morning = "Happy Coding";

  static String getMorning() {
    return morning;
  }
}
물론 결과는 해피토일리트였다.クラス名::メソッド名로 바꾸면 해피코딩을 먼저 할 수 있다.
그러나 여기서 Developer developer = new Developer();를 표시하기 위해 실례를 만들고 이 실례에서 호출했다. 그러나 처음에는 static method가
 Human.getMorning();
 Developer.getMorning();
그리고 실례를 거치지 않고 클래스 자체에서 인용하는 것이 가장 좋다.
실제로 위 코드를 IntelliJ로 직접 이동하면
オーバーライドできない로 주목받다.
(Special thanks to@kawamnv씨)

public static void main(String [] args)


주 방법을 호출할 때, 실례가 메모리에 존재하지 않기 때문에, 이 실례를 포함하는 클래스가 실례화되지 않아도 주 방법은 실행되어야 한다.

static 클래스


클래스 중의 클래스, 내부 클래스는 세 가지가 있는데 구성원 클래스, 로컬 클래스, 익명 클래스가 있다.
static 구성원 클래스는 구성원 클래스 중 하나로 선언된 위치는 클래스 블록에 있다(필드와 방법과 같은 위치).
그러나 엄밀히 말하면 static 구성원 클래스는 내부 클래스라고 부르기 어려우므로 완전히 다른 클래스로 표시하는 것이 좋다.
내부 클래스를 포함하는 클래스를 외부 클래스라고 부르면
외부 클래스나 실례와의 관계가 상대적으로 얇고 외부 클래스의static 구성원에게도 접근할 수 있다.
다른 static와 마찬가지로 class itself から参照されていない static method에서 사용합니다.
Outer.java
class Outer { // 外部クラス

  // メンバクラス➀ static クラス
  static class StaticInner {
    private Integer in;

    public Integer getIn() {
      return in;
    }

    public void setIn(Integer in) {
      this.in = in;
    }
  }

  // メンバクラス➁ 厳密的なメンバクラス
  class Inner {
    private String str;

    public String getStr() {
      return str;
    }

    public void setStr(String str) {
      this.str = str;
    }
  }
}
무관한 클래스와 주 방법의 호출은 다음과 같다.
Execute.java
class Execute {
  public static void main(String[] args) {
    // static クラス
    Outer.StaticInner staticInner = new Outer.StaticInner();

    // 厳密的なメンバクラス
    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();
  }
}
위의 예에서 엄격한 구성원류와 외부류에서 발생한 각 실례는 매우 강한 관계를 가지기 때문에 외부류 실례가 없으면 new를 진행할 수 없다.static 물건이 아니기 때문에 비static 멤버도 접근할 수 있습니다.

static 초기화

static {
  // 処理
}
static 초기화기는 클래스 불러오기 (.class 파일 불러오기) 에서 한 번만 실행되는 블록입니다.
실례의 어떤 종류를 설명하기 전이나 주 방법을 사용하기 전에 실행할 처리를 호출합니다.
물론 기술할 수 있는 것은static에만 한정된다.
용도가 있나요?계속 생각하고 있었어요.
public final static String VALUE;

static {
  VALUE = makeValue();
} 

/**
 * 特定条件下で値を動的に生成する
 * @return value 生成した値
 */
private static String makeValue() {
  // omit
}
며칠 전에 우연한 계기로 이런 사용법을 시도해 봤어요.
'실례화보다 이른 시기에 새로운 값을 한번 만들어보자'는 게 그걸 반복해서 쓰려는 목적이라 딱 맞는 것 같아요.

구조기와static 초기화

class Something {

  void printA() {
    System.out.print("t");
  }

  void printB() {
    System.out.print("e");
  }

  Something () {
    System.out.print("l");
    printB();
  }

  static {
    System.out.print("i");
  }
}

class StaticTest {
  static {
    System.out.print("T");
  }

  public static void main(String [] args) {
    System.out.print("o");
    new Something().printA();
  }
}
결과는 Toilet 입니다.
static 초기화기는 new(실례화)에 따라 마침내 호출된 구조기보다 초기 단계에 불렸다.

static import 선언


java5 이후에 가져왔습니다.
다음은 저번 투고의 제약조건을 만들 때 사용하는 원본 파일입니다.
CustomSize.java
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = {CustomSizeValidator.class})
public @interface CustomSize {
  // omit
}
실제로 外部クラス名.メンバクラス名ElementType는 긴 포장 이름의 엔음이기 때문에 위와 같이 명확하게 기술한다.
외부 반의 static 구성원이라면 엔음이 아니어도 사용할 수 있다.
import static java.lang.System.*;
import static java.lang.Math.*;

끝말


일찌감치 화장실일수록 문법의 기초를 재확인하는 것이 중요하다(살금살금)
이상

좋은 웹페이지 즐겨찾기