[java] Java의 CharSequence VS String?

Android에서 프로그래밍하면 대부분의 텍스트 값이로 예상됩니다 CharSequence.

왜 그런 겁니까? 장점은 무엇이며, CharSequenceover 를 사용할 때의 주된 영향은 String무엇입니까?

주요 차이점은 무엇이며 어떤 문제를 사용하고 서로 변환하면서 어떤 문제가 예상됩니까?



답변

문자열은 CharSequences 이므로 문자열을 사용할 수 있으며 걱정할 필요가 없습니다. Android는 StringBuffers와 같은 다른 CharSequence 객체도 지정할 수 있도록함으로써 도움을 주려고합니다.


답변

CharSequence= 인터페이스
String= 구체적인 구현

당신은 말했다 :

하나에서 다른 것으로 변환

에서 변환하는 것이 없습니다 String.

  • 모든 String대상 입니다 CharSequence.
  • 모든 CharSequence생산할 수 있습니다 String. 전화하십시오 CharSequence::toString. CharSequence발생하는 경우String 메서드는 자체 객체에 대한 참조를 반환합니다.

다시 말해 모든 String것이 a CharSequence이지만 모든 CharSequence것이 a는 아닙니다 String.

인터페이스 프로그래밍

안드로이드 프로그래밍, 대부분의 텍스트 값은 CharSequence에서 예상됩니다.

왜 그런 겁니까? CharSequence over String을 사용하면 어떤 이점이 있습니까?

일반적으로 인터페이스 프로그래밍은 구체적인 클래스 프로그래밍보다 낫습니다. 이는 유연성을 제공하므로 다른 코드를 손상시키지 않고 특정 인터페이스의 구체적인 구현간에 전환 할 수 있습니다.

API를 개발할 때다양한 상황에서 다양한 프로그래머가 사용할 를 가능한 가장 일반적인 인터페이스를 제공하고 사용하도록 코드를 작성하십시오. 이것은 호출 프로그래머에게 해당 인터페이스의 다양한 구현을 자유롭게 사용할 수 있도록합니다. 구현은 특정 상황에 가장 적합합니다.

예를 들어, Java Collections Framework를보십시오 . 당신의 API가 제공 또는 객체의 정렬 된 컬렉션을 소요하는 경우, 사용과 같이 메소드를 선언 List하기보다는 ArrayList, LinkedList또는 다른 어떤 제 3 자 구현 List.

여러 장소에서 사용되는 API를 작성하는 것과 달리 특정 장소에서 코드 만 사용하는 빠르고 더러운 작은 방법을 작성할 때 특정 콘크리트가 아닌 일반적인 인터페이스를 사용하는 데 신경 쓰지 않아도됩니다. 수업. 그러나 그럼에도 불구하고 가능한 가장 일반적인 인터페이스를 사용하는 것은 상처를줍니다.

주요 차이점은 무엇이며 예상되는 문제는 무엇입니까?

  • String당신은 전적으로 메모리에 하나의 텍스트가 있고 불변 이라는 것을 알고 있습니다.
  • 를 사용 CharSequence하면 구체적인 구현의 특정 기능이 무엇인지 알 수 없습니다.

CharSequence객체는 텍스트의 거대한 덩어리를 나타내고, 따라서 메모리 의미를 가지고 있습니다. 또는를 호출 할 때 함께 스티칭해야 toString하므로 성능 문제가 있는 별도의 추적 된 텍스트 덩어리가있을 수 있습니다. 구현시 원격 서비스에서 텍스트를 검색 할 수도 있으므로 대기 시간에 영향을 미칩니다.

서로 변환합니까?

일반적으로 앞뒤로 변환하지 않습니다. A String 입니다 CharSequence. 메소드가을 사용한다고 선언 CharSequence하면 호출 프로그래머가 String객체를 전달 StringBuffer하거나 a 또는와 같은 다른 것을 전달할 수 있습니다 StringBuilder. 메소드의 코드는 전달 된 모든 것을 사용하여 CharSequence메소드를 호출합니다 .

변환에 가장 가까운 것은 코드에 a가 수신되고 a CharSequence가 필요한 경우 String입니다. 아마도 당신은 인터페이스에 쓰여지지 String않고 클래스에 쓰여진 오래된 코드와 인터페이스하고있을 것입니다 CharSequence. 또는 반복적으로 반복하거나 분석하는 것과 같이 코드에서 텍스트를 집중적으로 사용할 수 있습니다. 이 경우 가능한 성능 저하를 한 번만 수행하려고합니다.toString . 그런 다음 완전히 기억에 담긴 단일 텍스트로 알고있는 것을 사용하여 작업을 진행하십시오.

뒤틀린 역사

허용 된 답변 에 대한 의견을 적어 둡니다 . CharSequence인터페이스는 기존의 클래스 구조로 개조, 그래서 몇 가지 중요한 미묘이 (가 equals()& hashCode()). 클래스 / 인터페이스에 태그가 지정된 다양한 버전의 Java (1, 2, 4 및 5)에 주목하십시오. 이상적으로 CharSequence처음부터 자리 잡았을 것입니다.

아래의 클래스 다이어그램은 Java 7/8에서 문자열 유형의 큰 그림을 보는 데 도움이 될 수 있습니다. 이 모든 것이 Android에 있는지 확실하지 않지만 전반적인 컨텍스트가 여전히 유용 할 수 있습니다.

다양한 문자열 관련 클래스 및 인터페이스 다이어그램


답변

CharSequence를 사용하는 것이 가장 좋습니다. 그 이유는 String이 CharSequence를 구현하기 때문에 CharSequence에 String을 전달할 수 있지만 CharSequence는 String을 구현하지 않기 때문에 CharSequence를 String에 전달할 수 없다는 것입니다. 또한 Android에서이 EditText.getText()메소드는 Editable을 리턴합니다. 이 메소드는 CharSequence도 구현하며 쉽게 문자열로 전달되지 않고 하나에 전달 될 수 있습니다. CharSequence는 모든 것을 처리합니다!


답변

일반적으로 인터페이스를 사용하면 최소한의 부수적 피해로 구현을 변경할 수 있습니다. java.lang.String은 매우 인기가 있지만 특정 상황에서 다른 구현을 사용하고 싶을 수도 있습니다. 문자열이 아닌 CharSequences를 중심으로 API를 빌드하면 코드에서이를 수행 할 수 있습니다.


답변

이것은 거의 확실하게 성능상의 이유입니다. 예를 들어 문자열이 포함 된 500k ByteBuffer를 통과하는 파서를 상상해보십시오.

문자열 내용을 반환하는 방법에는 3 가지가 있습니다.

  1. 구문 분석시 한 번에 한 문자 씩 String []을 작성하십시오. 시간이 많이 걸립니다. 캐시 된 참조를 비교하기 위해 .equals 대신 ==를 사용할 수 있습니다.

  2. 구문 분석시 오프셋을 사용하여 int []를 빌드 한 다음 get ()이 발생할 때 동적으로 문자열을 빌드하십시오. 각 문자열은 새 객체이므로 반환 값을 캐싱하지 않고 ==

  3. 구문 분석시 CharSequence []를 빌드하십시오. 바이트 버퍼로의 오프셋 이외의 새로운 데이터가 저장되지 않기 때문에 구문 분석은 # 1보다 훨씬 낮습니다. 얻을 때 String을 만들 필요가 없으므로 기존 객체에 대한 참조 만 반환하므로 성능은 # 1과 동일합니다 (# 2보다 훨씬 낫습니다).

CharSequence를 사용하면 얻을 수있는 처리 이점 외에도 데이터를 복제하지 않음으로써 메모리 공간을 줄일 수 있습니다. 예를 들어, 3 개의 텍스트 단락이 포함 된 버퍼가 있고 3 개 또는 단일 단락을 모두 반환하려는 경우이를 나타내려면 4 개의 문자열이 필요합니다. CharSequence를 사용하면 데이터가 포함 된 1 개의 버퍼와 시작 및 길이를 추적하는 CharSequence 구현의 4 개 인스턴스 만 필요합니다.


답변

실제 Android 코드에서 발생하는 문제는 CharSequence.equals와 비교하는 것이 유효하지만 반드시 의도 한대로 작동하지는 않는다는 것입니다.

EditText t = (EditText )getView(R.id.myEditText); // Contains "OK"
Boolean isFalse = t.getText().equals("OK"); // will always return false.

비교는

("OK").contentEquals(t.GetText()); 


답변

CharSequence

A CharSequence는 실제 클래스가 아닌 인터페이스입니다. 인터페이스는 인터페이스를 구현하는 경우 클래스에 포함해야하는 일련의 규칙 (방법)입니다. Android에서 a CharSequence는 다양한 유형의 텍스트 문자열을위한 우산입니다. 다음은 일반적인 것들입니다.

( 여기 에서 차이점에 대한 자세한 내용은 여기를 참조하십시오 .)

CharSequence객체 가 있으면 실제로 구현하는 클래스 중 하나의 객체입니다 CharSequence. 예를 들면 다음과 같습니다.

CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();

일반적인 우산 유형과 같은 장점은 CharSequence단일 방법으로 여러 유형을 처리 할 수 ​​있다는 것입니다. 예를 들어 CharSequence매개 변수로 a를 사용 하는 메서드가 있으면 a String또는 a를 전달할 수 있으며 SpannableStringBuilder둘 중 하나를 처리합니다.

public int getLength(CharSequence text) {
    return text.length();
}

a String는 단지 한 종류 일 뿐이라고 말할 수 CharSequence있습니다. 그러나와 달리 CharSequence실제 클래스이므로 객체를 만들 수 있습니다. 그래서 당신은 이것을 할 수 있습니다 :

String myString = new String();

그러나 당신은 이것을 할 수 없습니다 :

CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated

준수하는 CharSequence규칙 목록 일 뿐이 므로 String다음을 수행 할 수 있습니다.

CharSequence myString = new String();

즉, 메소드가을 요청할 때마다을 지정하는 CharSequence것이 String좋습니다.

String myString = "hello";
getLength(myString); // OK

// ...

public int getLength(CharSequence text) {
    return text.length();
}

그러나 그 반대는 사실이 아닙니다. 메소드가 String매개 변수를 사용 하는 경우 CharSequence실제로는 SpannableString또는 다른 종류 일 수 있기 때문에 일반적으로로만 알려진 것을 전달할 수 없습니다 CharSequence.

CharSequence myString = "hello";
getLength(myString); // error

// ...

public int getLength(String text) {
    return text.length();
}