Kotlin에서 상수를 만드는 것이 어떻게 권장됩니까? 명명 규칙은 무엇입니까? 설명서에서 찾지 못했습니다.
companion object {
//1
val MY_CONST = "something"
//2
const val MY_CONST = "something"
//3
val myConst = "something"
}
아니면 ...?
Kotlin에서 상수를 만드는 것이 어떻게 권장됩니까? 명명 규칙은 무엇입니까? 설명서에서 찾지 못했습니다.
companion object {
//1
val MY_CONST = "something"
//2
const val MY_CONST = "something"
//3
val myConst = "something"
}
아니면 ...?
답변:
Kotlin에서 클래스에서 사용할 로컬 상수를 만들려면 아래와 같이 만들 수 있습니다
val MY_CONSTANT = "Constants"
그리고 자바의 public static final 과 같이 kotlin에 public 상수를 만들려면 다음과 같이 만들 수 있습니다.
companion object{
const val MY_CONSTANT = "Constants"
}
Constants.kt
어떻게 사용합니까?
companion object
@piotrpo의 답변이 받아 들여 져야한다고 생각 하지 않아도됩니다.
컴패니언 개체를 사용하지 마십시오. 후드 뒤에는 필드에 액세스 할 수 있도록 getter 및 setter 인스턴스 메소드가 작성됩니다. 인스턴스 메소드 호출은 정적 메소드 호출보다 기술적으로 비쌉니다.
public class DbConstants {
companion object {
val TABLE_USER_ATTRIBUTE_EMPID = "_id"
val TABLE_USER_ATTRIBUTE_DATA = "data"
}
대신에 상수를 정의하십시오 object
.
권장 연습 :
object DbConstants {
const val TABLE_USER_ATTRIBUTE_EMPID = "_id"
const val TABLE_USER_ATTRIBUTE_DATA = "data"
}
다음과 같이 전 세계에 액세스하십시오.
DbConstants.TABLE_USER_ATTRIBUTE_EMPID
const val
컴패니언 오브젝트 const val
의 일반 오브젝트와 다른 오브젝트가 될 수있는 방법 (예를 들어 const
, 컴패니언 오브젝트의 경우 생략 한 것 같습니다. 추가 const
하면 예제의 성능이 동일해야 함)
const val
선언하는 companion object
것이 맞습니다.
우선 상수에 대한 Kotlin의 명명 규칙은 java와 동일합니다 (예 : MY_CONST_IN_UPPERCASE).
클래스 선언 외부에서 const를 배치해야합니다 .
두 가지 가능성 : 클래스 파일에 const를 선언하십시오 (const는 클래스와 명확한 관계가 있습니다)
private const val CONST_USED_BY_MY_CLASS = 1
class MyClass {
// I can use my const in my class body
}
전역 const를 저장할 전용 constants.kt 파일을 만듭니다 (여기에서 프로젝트 전체에서 const를 광범위하게 사용하려는 경우).
package com.project.constants
const val URL_PATH = "https:/"
그런 다음 필요한 곳으로 가져와야합니다.
import com.project.constants
MyClass {
private fun foo() {
val url = URL_PATH
System.out.print(url) // https://
}
}
바이트 코드가 생성 될 때 쓸모없는 객체가 만들어지기 때문에 이것은 훨씬 덜 깨끗합니다.
MyClass {
companion object {
private const val URL_PATH = "https://"
const val PUBLIC_URL_PATH = "https://public" // Accessible in other project files via MyClass.PUBLIC_URL_PATH
}
}
const 대신 val로 선언하면 더 나빠 집니다 (컴파일러는 쓸모없는 객체 + 쓸모없는 함수를 생성합니다) :
MyClass {
companion object {
val URL_PATH = "https://"
}
}
kotlin에서 const는 기본 유형을 보유 할 수 있습니다. 함수를 전달하려면 @JvmField 주석을 추가해야합니다. 컴파일 타임에는 공개 정적 최종 변수로 변환됩니다. 그러나 기본 유형보다 느립니다. 피하십시오.
@JvmField val foo = Foo()
컴파일 타임에 알려진 값은 상수로 표시 될 수 있습니다.
이름 지정 규칙은 Java 규칙을 따라야하며 Java 코드에서 사용될 때 올바르게 표시되어야합니다 (어쨌든 컴패니언 객체로는 달성하기 어렵습니다).
적절한 상수 선언은 다음과 같습니다.
const val MY_CONST = "something"
const val MY_INT = 1
Naming conventions should follow Java ones
- 왜?
If in doubt, default to the Java Coding Conventions
Kotlin에서 상수를 선언하기 위해 클래스, 객체 또는 동반 객체가 필요하지 않습니다. 모든 상수를 보유한 파일을 선언하고 (예 : Constants.kt 또는 기존 Kotlin 파일에 넣을 수 있음) 파일 내부에 상수를 직접 선언 할 수 있습니다. 컴파일 타임에 알려진 상수는로 표시되어야합니다 const
.
따라서이 경우 다음과 같아야합니다.
const val MY_CONST = "something"
다음을 사용하여 상수를 가져올 수 있습니다.
import package_name.MY_CONST
이 링크를 참조 할 수 있습니다
const val valName = valValue
클래스 이름 앞에을 넣으면 이런 식으로
public static final YourClass.Kt
그 public static final
값 을 가질 것 입니다.
코 틀린 :
const val MY_CONST0 = 0
const val MY_CONST1 = 1
data class MyClass(var some: String)
자바 디 컴파일 :
public final class MyClassKt {
public static final int MY_CONST0 = 0;
public static final int MY_CONST1 = 1;
}
// rest of MyClass.java
class Myclass {
companion object {
const val MYCONSTANT = 479
}
const
키워드 를 사용 하거나 @JvmField
Java를 정적 최종 상수로 만드는 두 가지 선택 사항이 있습니다 .
class Myclass {
companion object {
@JvmField val MYCONSTANT = 479
}
@JvmField
주석을 사용하면 주석이 컴파일 된 후 상수가 Java에서 호출하는 방식으로 입력됩니다.
자바에서 호출하는 것처럼 코드에서 컴패니언 상수를 호출하면 컴파일러가이를 대체합니다.
그러나 const 키워드를 사용하면 상수 값이 인라인됩니다. 인라인 i는 실제 값이 컴파일 된 후 사용됨을 의미합니다.
그래서 여기에 컴파일러가 당신을 위해 할 일이 요약되어 있습니다 :
//so for @JvmField:
Foo var1 = Constants.FOO;
//and for const:
Foo var1 = 479
코 틀린 정적 및 상수 값 및 메소드 선언
object MyConstant {
@JvmField // for access in java code
val PI: Double = 3.14
@JvmStatic // JvmStatic annotation for access in java code
fun sumValue(v1: Int, v2: Int): Int {
return v1 + v2
}
}
어디서나 액세스 가치
val value = MyConstant.PI
val value = MyConstant.sumValue(10,5)
마찬가지로 키워드로 val
정의 된 변수 const
는 변경할 수 없습니다. 여기서 차이점은 const
컴파일 타임에 알려진 변수에 사용 된다는 것 입니다.
변수를 선언하는 const
것은 static
Java 에서 키워드를 사용하는 것과 매우 유사합니다 .
코 틀린에서 const 변수를 선언하는 방법을 보자 :
const val COMMUNITY_NAME = "wiki"
Java로 작성된 유사한 코드는 다음과 같습니다.
final static String COMMUNITY_NAME = "wiki";
위의 답변에 추가-
@JvmField
Kotlin 컴파일러에게이 속성에 대한 getter / setter를 생성하지 않고 필드로 노출하지 않도록 지시하는 데 사용됩니다.
@JvmField
val COMMUNITY_NAME: "Wiki"
정적 필드
명명 된 객체 또는 컴패니언 객체에 선언 된 Kotlin 속성에는 해당 명명 된 객체 또는 컴패니언 객체를 포함하는 클래스에 정적 백업 필드가 있습니다.
일반적으로 이러한 필드는 비공개이지만 다음 방법 중 하나로 노출 될 수 있습니다.
@JvmField
주석;lateinit
개질제;const
수정 자.자세한 내용은 여기-https: //kotlinlang.org/docs/reference/java-to-kotlin-interop.html#instance-fields
답변에 언급되지 않은 것은을 사용하는 오버 헤드입니다 companion objects
. 여기서 읽을 수 있듯이 컴패니언 객체는 실제로 객체이며 객체를 만들면 리소스가 소비됩니다. 또한 상수를 사용할 때마다 둘 이상의 게터 함수를 거쳐야 할 수도 있습니다. 필요한 것이 소수의 기본 상수라면 성능 을 높이고를 피하기 위해 사용 val
하는 것이 좋습니다companion object
.
TL; DR; 기사의 :
컴패니언 객체를 사용하면 실제로이 코드가됩니다.
class MyClass {
companion object {
private val TAG = "TAG"
}
fun helloWorld() {
println(TAG)
}
}
이 코드로 :
public final class MyClass {
private static final String TAG = "TAG";
public static final Companion companion = new Companion();
// synthetic
public static final String access$getTAG$cp() {
return TAG;
}
public static final class Companion {
private final String getTAG() {
return MyClass.access$getTAG$cp();
}
// synthetic
public static final String access$getTAG$p(Companion c) {
return c.getTAG();
}
}
public final void helloWorld() {
System.out.println(Companion.access$getTAG$p(companion));
}
}
따라서 피하십시오.
Kotlin에서 상수를 정의 할 수있는 몇 가지 방법이 있습니다.
컴패니언 객체 사용
companion object {
const val ITEM1 = "item1"
const val ITEM2 = "item2"
}
모든 클래스 내에서 위의 컴패니언 객체 블록을 사용하고이 블록 자체 내의 모든 필드를 정의 할 수 있습니다. 그러나이 방법에는 문제가있다.
컴패니언 객체의 멤버는 다른 언어에서는 정적 멤버처럼 보이지만 런타임에 여전히 실제 객체의 인스턴스 멤버이며 인터페이스를 구현할 수 있습니다.
컴패니언 객체를 사용하여 상수를 만들고 디 컴파일 된 바이트 코드 를 보면 다음과 같은 결과가 나타납니다.
ClassName.Companion Companion = ClassName.Companion.$$INSTANCE;
@NotNull
String ITEM1 = "item1";
@NotNull
String ITEM2 = "item2";
public static final class Companion {
@NotNull
private static final String ITEM1 = "item1";
@NotNull
public static final String ITEM2 = "item2";
// $FF: synthetic field
static final ClassName.Companion $$INSTANCE;
private Companion() {
}
static {
ClassName.Companion var0 = new ClassName.Companion();
$$INSTANCE = var0;
}
}
여기 에서 컴패니언 객체의 멤버가 다른 언어의 정적 멤버처럼 보이지만 런타임에 여전히 실제 객체의 인스턴스 멤버 인 경우에도 문서에서 말한 내용을 쉽게 확인할 수 있습니다 . 필요한 것보다 추가 작업을 수행하고 있습니다.
다음과 같이 컴패니언 객체를 사용할 필요가없는 다른 방법이 있습니다.
object ApiConstants {
val ITEM1: String = "item1"
}
위의 스 니펫 바이트 코드의 디 컴파일 된 버전을 보면 다음과 같이 보일 것입니다.
public final class ApiConstants {
private static final String ITEM1 = "item1";
public static final ApiConstants INSTANCE;
public final String getITEM1() {
return ITEM1;
}
private ApiConstants() {
}
static {
ApiConstants var0 = new ApiConstants();
INSTANCE = var0;
CONNECT_TIMEOUT = "item1";
}
}
위의 디 컴파일 된 코드가 보이면 각 변수에 대해 get 메소드를 작성하는 것입니다. 이 get 메소드는 전혀 필요하지 않습니다.
이 get 메소드를 제거하려면 아래처럼 val 앞에 const 를 사용해야 합니다.
object ApiConstants {
const val ITEM1: String = "item1"
}
위의 스 니펫의 디 컴파일 된 코드가 표시되면 코드의 백그라운드 변환이 가장 적기 때문에 쉽게 읽을 수 있습니다.
public final class ApiConstants {
public static final String ITEM1 = "item1";
public static final ApiConstants INSTANCE;
private ApiConstants() {
}
static {
ApiConstants var0 = new ApiConstants();
INSTANCE = var0;
}
}
상수를 만드는 가장 좋은 방법입니다.
프리미티브 및 문자열의 경우 :
/** The empty String. */
const val EMPTY_STRING = ""
다른 경우 :
/** The empty array of Strings. */
@JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
예:
/*
* Copyright 2018 Vorlonsoft LLC
*
* Licensed under The MIT License (MIT)
*/
package com.vorlonsoft.android.rate
import com.vorlonsoft.android.rate.Constants.Utils.Companion.UTILITY_CLASS_MESSAGE
/**
* Constants Class - the constants class of the AndroidRate library.
*
* @constructor Constants is a utility class and it can't be instantiated.
* @since 1.1.8
* @version 1.2.1
* @author Alexander Savin
*/
internal class Constants private constructor() {
/** Constants Class initializer block. */
init {
throw UnsupportedOperationException("Constants$UTILITY_CLASS_MESSAGE")
}
/**
* Constants.Date Class - the date constants class of the AndroidRate library.
*
* @constructor Constants.Date is a utility class and it can't be instantiated.
* @since 1.1.8
* @version 1.2.1
* @author Alexander Savin
*/
internal class Date private constructor() {
/** Constants.Date Class initializer block. */
init {
throw UnsupportedOperationException("Constants.Date$UTILITY_CLASS_MESSAGE")
}
/** The singleton contains date constants. */
companion object {
/** The time unit representing one year in days. */
const val YEAR_IN_DAYS = 365.toShort()
}
}
/**
* Constants.Utils Class - the utils constants class of the AndroidRate library.
*
* @constructor Constants.Utils is a utility class and it can't be instantiated.
* @since 1.1.8
* @version 1.2.1
* @author Alexander Savin
*/
internal class Utils private constructor() {
/** Constants.Utils Class initializer block. */
init {
throw UnsupportedOperationException("Constants.Utils$UTILITY_CLASS_MESSAGE")
}
/** The singleton contains utils constants. */
companion object {
/** The empty String. */
const val EMPTY_STRING = ""
/** The empty array of Strings. */
@JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
/** The part 2 of a utility class unsupported operation exception message. */
const val UTILITY_CLASS_MESSAGE = " is a utility class and it can't be instantiated!"
}
}
}
public static final
Java 의 필드에 해당하는 것을 원하면const val
컴패니언 객체에서 사용 하십시오.private static final
필드와 공개 게터 를 원하면val
컴패니언 객체에 사용 하십시오.