Companion object 를 쓸 줄 안다 고요?아마 아니 야!
사용 방법 은 대략 다음 과 같다.
class Main private constructor(){
private var id: Int? = null
companion object {
var previousId = -1
fun newInstance(): Main {
val instance = Main()
instance.id = previousId++
}
}
fun main(args: Array) {
val main = Main.newInstance()
print((Main.previousId)
}
}
이것 은 공장 방법 입 니 다. 사용 해 보면 자바 의 정적 구성원 과 매우 비슷 합 니 다. 그러나 우 리 는 이 필드 들 이 사실은 다른 대상 의 구성원 이라는 것 을 기억 해 야 합 니 다.컴 파일 러 가 또 몰래 우 리 를 도와 뭔 가 를 해 주 었 다)
언뜻 보기 에는 별 문제 가 없 는 것 같 습 니 다. 우리 자바 코드 도 이렇게 쓰 여 있 습 니 다. 독자 들 이 저 에 게 물 어 볼 것 같 습 니 다. 왜 반생 대상 만 알 고 있 으 면 안 되 는 지 이 정도 의 용법 이 아 닙 니까?
서 두 르 지 마라, 우리 가 바이트 번 호 를 벗 겨 보 자.
// access flags 0x8
static ()V
NEW Main$Companion
DUP
ACONST_NULL
INVOKESPECIAL Main$Companion. (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
PUTSTATIC Main.Companion : LMain$Companion;
L0
LINENUMBER 5 L0
ICONST_M1
PUTSTATIC Main.previousId : I
RETURN
MAXSTACK = 3
MAXLOCALS = 0
우 리 는 이 부분 을 보 았 습 니 다. Main 류 가 불 러 올 때 Main $Companion 류 의 대상 을 만 들 었 습 니 다. 이것 은 동반 대상 이 확실히 대상 이 고 우 리 는 주요 정적 구성원 으로 사용 하 는 구성원 들 이 모두 이 대상 의 구성원 임 을 증명 합 니 다.
그러면 컴 파일 러 가 우리 에 게 만들어 준 이런 종류의 바이트 코드 를 살 펴 보 자.
// access flags 0x2
private ()V
L0
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL java/lang/Object. ()V
RETURN
L1
LOCALVARIABLE this LMain$Companion; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1001
public synthetic (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
L0
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL Main$Companion. ()V
RETURN
L1
LOCALVARIABLE this LMain$Companion; L0 L1 0
LOCALVARIABLE $constructor_marker Lkotlin/jvm/internal/DefaultConstructorMarker; L0 L1 1
MAXSTACK = 1
MAXLOCALS = 2
우 리 는 기본 적 인 구조 함 수 를 제외 하고 컴 파일 러 가 그것 에 새로운 구조 함 수 를 합성 한 것 을 볼 수 있다.
또한 get, set 방법 으로 previousId 필드 를 방문 하여 대상 구성원 에 게 get, set 함 수 를 생 성 하 는 것 도 정상 입 니 다.
// access flags 0x11
public final getPreviousId()I
L0
LINENUMBER 5 L0
INVOKESTATIC Main.access$getPreviousId$cp ()I
IRETURN
L1
LOCALVARIABLE this LMain$Companion; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x11
public final setPreviousId(I)V
// annotable parameter count: 1 (visible)
// annotable parameter count: 1 (invisible)
L0
LINENUMBER 5 L0
ILOAD 1
INVOKESTATIC Main.access$setPreviousId$cp (I)V
RETURN
L1
LOCALVARIABLE this LMain$Companion; L0 L1 0
LOCALVARIABLE I L0 L1 1
MAXSTACK = 1
MAXLOCALS = 2
잠깐 만!왜 INVOKESTATIC 지령 이 있어!나 는 어떻게 또 Main 의 정적 방법 을 사용 하 는 지 눈 여 겨 보 았 다. 고 개 를 돌려 Main 의 바이트 코드 를 보 았 다. 과연 이런 방법 이 있 었 다.
// access flags 0x1019
public final static synthetic access$getPreviousId$cp()I
L0
LINENUMBER 1 L0
GETSTATIC Main.previousId : I
IRETURN
L1
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x1019
public final static synthetic access$setPreviousId$cp(I)V
L0
LINENUMBER 1 L0
ILOAD 0
PUTSTATIC Main.previousId : I
RETURN
L1
LOCALVARIABLE I L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
아 쉽 습 니 다. OOP 를 한 번 조작 하면 여러 가지 방법 이 호출 되 었 습 니 다. 마지막 으로 Main 에 정적 구성원 을 만 들 었 고 id 에 접근 하 는 방법 도 생 성 했 습 니 다.
// access flags 0x1019
public final static synthetic access$getId$p(LMain;)Ljava/lang/Integer;
L0
LINENUMBER 1 L0
ALOAD 0
GETFIELD Main.id : Ljava/lang/Integer;
ARETURN
L1
LOCALVARIABLE $this LMain; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1019
public final static synthetic access$setId$p(LMain;Ljava/lang/Integer;)V
L0
LINENUMBER 1 L0
ALOAD 0
ALOAD 1
PUTFIELD Main.id : Ljava/lang/Integer;
RETURN
L1
LOCALVARIABLE $this LMain; L0 L1 0
LOCALVARIABLE Ljava/lang/Integer; L0 L1 1
MAXSTACK = 2
MAXLOCALS = 2
나 는 기본 적 인 공장 방법 을 실현 하고 싶 은 데, 나 에 게 이렇게 많은 방법 을 만들어 줄 필요 가 있 습 니까?저 는 가만히 있 지 못 할 것 입 니 다. 저 는 또 장난 을 치기 시 작 했 습 니 다. previousId 는 정적 인 구성원 입 니 다. 그러면 이 를 진정한 정적 인 구성원 으로 만 들 방법 을 생각 하 세 요. new Instance 방법 은 원래 정적 인 대상 을 만 드 는 방법 이기 도 합 니 다.
@file:JvmName("Main")
@JvmField
var previousId = -1
class Main private constructor() {
private var id: Int? = null
companion object {
@JvmStatic
fun newInstance(): Main {
val instance = Main()
instance.id = previousId++
}
}
fun main(args: Array) {
val main = Main.newInstance()
print((previousId)
}
}
나 는 이전에 이미 여러분 과 최상 위 멤버 들 의 협조
@JvmField 의 효과 에 대해 토론 한 적 이 있 습 니 다. @ file: JvmName 은 컴 파일 러 의 모든 최상 위 멤버 들 에 게 Main 과 같은 종류 에 넣 으 라 고 알 렸 습 니 다. 우 리 는 컴 파일 러 가 우리 에 게 그렇게 많은 추가 방법 을 만 드 는 비용 을 더 이상 받 지 않 아 도 됩 니 다. @JvmStatic 컴 파일 러 가 new Instance 방법 을 정적 인 방법 으로 직접 컴 파일 하 게 할 것 입 니 다.이 때 생 성 된 바이트 코드 를 보십시오:
// access flags 0x1001
public synthetic (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
L0
LINENUMBER 9 L0
ALOAD 0
INVOKESPECIAL Main$Companion. ()V
RETURN
L1
LOCALVARIABLE this LMain$Companion; L0 L1 0
LOCALVARIABLE $constructor_marker Lkotlin/jvm/internal/DefaultConstructorMarker; L0 L1 1
MAXSTACK = 1
MAXLOCALS = 2
Main $Companion 류 라 는 생 성 된 구조 함 수 를 제외 하고 컴 파일 러 는 우리 에 게 구 부 러 진 방법 을 만 들 지 않 을 것 입 니 다. 완벽 합 니 다!
우리 가 정 리 를 해 보 자. 사실은 동반 대상 에서 구성원 변 수 를 정의 하 는 것 을 피하 고 파일 에서 최상 위 변 수 를 정의 하 는 것 이다. 또한 동반 대상 중의 함 수 를 모두
@JvmStatic 로 수식 하여 진정한 정적 함수 로 만 들 수 있다.다음 에 우 리 는 다시 Kotlin 의 독특한 유형
Range 을 벗 겨 냅 니 다.다음으로 전송:https://juejin.im/post/5c9b8a595188251d093d14e5
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.