Java에서 String 클래스가 final로 선언 된 이유는 무엇입니까?
java.lang.String
Java에서 클래스 가 final로 선언 되었다는 것을 알았을 때 왜 그런지 궁금했습니다. 그때 대답을 찾지 못했지만이 게시물 : Java에서 String 클래스의 복제본을 만드는 방법은 무엇입니까? 내 질문을 상기시켰다.
물론 String은 내가 필요한 모든 기능을 제공하며 String 클래스의 확장이 필요한 작업은 생각하지 못했지만 여전히 누군가가 필요한 것을 알 수는 없습니다!
그렇다면 디자이너가 최종 결정을 내릴 때 디자이너의 의도가 무엇인지 아는 사람이 있습니까?
변경 불가능한 객체 로 문자열을 구현하는 것이 매우 유용 합니다 . 당신은에 대해 읽어야 불변성 그것에 대해 더 이해하기.
불변 개체의 장점 중 하나 는
중복을 단일 인스턴스로 지정하여 중복을 공유 할 수 있습니다.
( 여기에서 ).
문자열이 최종이 아닌 경우 서브 클래스를 작성하고 "문자열로 볼 때"와 유사하지만 실제로는 다른 두 개의 문자열을 가질 수 있습니다.
위의 답변에서 이미 언급 한 두 가지 이유를 간략히 설명 하는 좋은 기사 입니다.
- 보안 : 시스템은 변경 될 걱정없이 민감한 읽기 전용 정보를 전달할 수 있습니다.
- 성능 : 불변의 데이터는 스레드 안전을 만드는 데 매우 유용합니다.
그리고 이것은 아마도 그 기사에서 가장 자세한 주석 일 것입니다. Java 및 보안 문제의 문자열 풀과 관련이 있습니다. 문자열 풀에 들어갈 내용을 결정하는 방법에 대해 설명합니다. 문자의 순서가 동일하면 두 문자열이 동일하다고 가정하면 누가 먼저 보안 문제에 도달하는지에 대한 경쟁 조건이 있습니다. 그렇지 않은 경우, 문자열 풀에는 중복 문자열이 포함되므로 우선 문자열을 사용하는 이점을 잃게됩니다. 그냥 읽어 보시겠습니까?
문자열을 확장하면 같고 인턴으로 혼란 스러울 수 있습니다. JavaDoc은 다음과 같습니다.
이 문자열을 지정된 객체와 비교합니다. 인수가 널이 아니고이 오브젝트와 동일한 문자 시퀀스를 나타내는 String 오브젝트 인 경우에만 결과가 참입니다.
java.lang.String
최종이 아니라고 가정하면 SafeString
a String
와 같고 그 반대도 마찬가지입니다. 그것들은 동일한 문자 시퀀스를 나타 내기 때문입니다.
당신이 적용하면 어떻게 될까 intern
A를 SafeString
- 것 SafeString
JVM의 문자열 풀로 이동? ClassLoader
모두는 개체를 SafeString
다음 JVM의 수명 동안 제자리에 고정 얻을 것이다으로 보류 참조. 캐릭터 시퀀스를 처음으로 인턴 할 수있는 사람에 대한 경쟁 조건이 생길 수 있습니다. 어쩌면 당신 SafeString
이 이길 수도 있고 다른 클래스 로더에 의해로드 String
될 수도 있습니다 SafeString
(따라서 다른 클래스).
당신이 수영장에서 레이스에서 이겼다면, 이것은 진정한 싱글 톤이 될 것 secretKey.intern().getClass().getClassLoader()
입니다.
또는 JVM은 구체적인 String 객체 (하위 클래스 없음) 만 풀에 추가되도록하여이 구멍을 차단할 수 있습니다.
등호가 같은 구현 된 경우 있음 SafeString
! = String
다음 SafeString.intern
! = String.intern
및 SafeString
풀에 추가되어야 할 것이다. 그러면 수영장이 <Class, String>
대신 수영장이되며 수영장에 <String>
들어가기 위해 필요한 것은 새로운 클래스 로더입니다.
String이 불변이거나 최종적인 가장 중요한 이유는 클래스 로딩 메커니즘에 의해 사용되므로 심오하고 근본적인 보안 측면을 가지고 있기 때문입니다.
문자열이 변경 가능하거나 최종적이지 않은 경우 "java.io.Writer"로드 요청이 "mil.vogoon.DiskErasingWriter"로드로 변경되었을 수 있습니다.
String
Java의 핵심 클래스이며 많은 것들이 불변의 것과 같은 특정 방식으로 작동합니다.
클래스를 만들면 final
이러한 가정을 어길 수있는 서브 클래스가 방지됩니다.
지금도 리플렉션을 사용하는 경우 문자열을 끊을 수 있습니다 (값 또는 해시 코드 변경). 보안 관리자를 사용하여 리플렉션을 중지 할 수 있습니다. 경우 String
아니었다 final
, 모든 사람이 그것을 할 수 있습니다.
선언되지 않은 다른 클래스를 final
사용하면 다소 깨진 서브 클래스를 정의 할 수 List
있지만 (예를 들어 잘못된 위치에 추가 할 수 있음 ) 적어도 JVM은 핵심 작업의 클래스에 의존하지 않습니다.
브루노가 말했듯이 그것은 불변성에 관한 것입니다. Strings뿐만 아니라 Double, Integer, Character 등과 같은 래퍼도 중요합니다. 여기에는 여러 가지 이유가 있습니다.
- 스레드 안전
- 보안
- Java 자체에서 관리되는 힙 (다른 방식으로 가비지 수집 된 일반 힙과는 다름)
- 메모리 관리
기본적으로 프로그래머는 문자열을 변경하지 않을 수 있습니다. 또한 작동 방식을 알고 있으면 메모리 관리 기능을 향상시킬 수 있습니다. "hello"와 같이 두 개의 동일한 문자열을 하나씩 만들어보십시오. 디버깅하는 경우 동일한 ID를 가지고 있음을 알 수 있습니다. 즉, 동일한 SAME 개체임을 의미합니다. 이것은 Java가 당신을 그렇게 하자는 사실 때문입니다. 문자열이 변경 가능하면 가능하지 않습니다. 그들은 결코 변하지 않을 것이기 때문에 같은 것을 가질 수 있습니다. 따라서 1,000,000 개의 문자열 "hello"를 작성하기로 결정한 경우 실제로 수행하는 작업은 "hello"에 대한 1,000,000 개의 포인터를 작성하는 것입니다. 문자열이나 함수의 래퍼에 대한 모든 기능을 사용하면 다른 객체가 생성됩니다 (객체 ID를 보면 다시 변경됩니다).
Aditionally 자바 마지막이되지 않습니다 반드시 그 객체는 변경할 수 없습니다 의미 (그것은 ++ 예 : C 다릅니다). 즉, 주소가 가리키는 주소는 변경할 수 없지만 속성 및 / 또는 속성은 변경할 수 있습니다. 따라서 어떤 경우에는 불변성과 최종의 차이를 이해하는 것이 실제로 중요 할 수 있습니다.
HTH
참고 문헌 :
- http://chaoticjava.com/posts/how-does-garbage-collection-work/
- http://chaoticjava.com/posts/gc-tips-and-memory-leaks/
- http://java.sun.com/j2se/1.5/pdf/jdk50_ts_guide.pdf
It may have been to simplify implementation. If you design a class that will be inheritable by users of the class, then you have a whole new set of use cases to consider into your design. What happens if they do this or that with X proptected field? Making it final they can focus on getting the public interface working correctly and make sure it's solid.
With a lot of good points already mentined I would like to add another one -one of the reason of Why String is immutable in Java is to allow String to cache its hashcode , being immutable String in Java caches its hashcode, and do not calculate every time we call hashcode method of String, which makes it very fast as hashmap key to be used in hashmap in Java.
In short because String is immutable, no one can change its contents once created which guarantees hashCode of String to be same on multiple invocation.
If you see String
class has is declared as
/** Cache the hash code for the string */
private int hash; // Default to 0
and hashcode()
function is as follows -
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
If it is already computer just return the value.
Apart from the obvious reasons suggested in other answers, one thought of making String class final could also be related to virtual methods performance overhead. Remember String is a heavy class, making this final, means no sub-implementation for sure, means no indirection calling overhead ever. Of course now we have things like virtual invoke and others, which always does these kind of optimization for you.
In addition to the reasons mentioned in other answers (security, immutability, performance) it should be noted that String
has special language support. You can write String
literals and there's support for the +
operator. Allowing programmers to subclass String
, would encourage hacks such as:
class MyComplex extends String { ... }
MyComplex a = new MyComplex("5+3i");
MyComplex b = new MyComplex("7+4i");
MyComplex c = new MyComplex(a + b); // would work since a and b are strings,
// and a string + a string is a string.
Well, I have some different thought I am not sure whether I am correct or not but in Java String is the only object which can be treated as a primitive data type as well I mean we can create a String object as String name="java". Now like others primitive datatypes which are copy by value not copy by reference String is expected to have same behavior so thats why String is final. Thats what my thought it. Please ignore if its completely illogical.
The finality of strings also defends them as a standard. In C++ you can create subclasses of string, so every programming shop could have its own version of string. This would lead to a lack of a strong standard.
To make sure we do not get a better implementation. It should of course have been an interface.
[edit] Ah, getting more clueless down votes. The answer is perfectly serious. I've had to program my way around the stupid String implementation several times, leading to severe performance & productivity loss
Let's say you have an Employee
class that has a method greet
. When the greet
method is called it simply prints Hello everyone!
. So that is the expected behavior of greet
method
public class Employee {
void greet() {
System.out.println("Hello everyone!");
}
}
Now, let GrumpyEmployee
subclass Employee
and override greet
method as shown below.
public class GrumpyEmployee extends Employee {
@Override
void greet() {
System.out.println("Get lost!");
}
}
Now in the below code have a look at the sayHello
method. It takes Employee
instance as a parameter and calls the greet method hoping that it would say Hello everyone!
But what we get is Get lost!
. This change in behavior is because of Employee grumpyEmployee = new GrumpyEmployee();
public class TestFinal {
static Employee grumpyEmployee = new GrumpyEmployee();
public static void main(String[] args) {
TestFinal testFinal = new TestFinal();
testFinal.sayHello(grumpyEmployee);
}
private void sayHello(Employee employee) {
employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
}
}
This situation can be avoided if the Employee
class was made final
. Now it's up to your imagination the amount of chaos a cheeky programmer could cause if String
Class was not declared as final
.
Does JVM know what is immutable? Answer is No, The constant pool contains all immutable fields but all immutable fields/objects are not stored in constant pool only. Only we implement it in a way that it achieves immutablity and its features. CustomString could be implemented without making it final using MarkerInterface which would provide java special behaviour for its pooling, the feature is still awaited!
Most of the answers are related to the immutability -- why an object of String type cannot be updated in place. There is a lot of good discussion here, and the Java community would do well to adopt immutability as a principal. (Not holding my breath.)
However the OP's question is about why it's final -- why can it not be extended. Some here did take this on, but I would agree with the OP that there is a real gap here. Other language allow devs create new nominal types for a type. For example in Haskell I can create the following new types that are identical at run-time as text, but provide bind-safety at compile time.
newtype AccountCode = AccountCode Text
newtype FundCode = FundCode Text
So I would put the following suggestion forward as an enhancement to the Java language:
newtype AccountCode of String;
newtype FundCode of String;
AccountCode acctCode = "099876";
FundCode fundCode = "099876";
acctCode.equals(fundCode); // evaluates to false;
acctCode.toString().equals(fundCode.toString()); // evaluates to true;
acctCode=fundCode; // compile error
getAccount(fundCode); // compile error
(Or perhaps we could start to ween ourselves off Java)
If you create a string once It will consider that,it is a object if you want to modify that, it is not possible,it will create new object.
참고URL : https://stackoverflow.com/questions/2068804/why-is-the-string-class-declared-final-in-java
'IT' 카테고리의 다른 글
Rails 4-강력한 매개 변수-중첩 된 객체 (0) | 2020.06.28 |
---|---|
코드로 조각 태그를 설정하는 방법은 무엇입니까? (0) | 2020.06.28 |
PHP에서 두 문자열의 차이점을 강조 (0) | 2020.06.28 |
Javascript에서 가속도계 / 자이로 스코프 데이터에 액세스하는 방법은 무엇입니까? (0) | 2020.06.28 |
파이썬에서 두 목록에 동일한 요소가 포함되어 있다고 주장하는 방법은 무엇입니까? (0) | 2020.06.28 |