Nice programing

배열 객체이지만 기본 클래스로 사용할 수없는 이유는 무엇입니까?

nicepro 2020. 11. 15. 11:46
반응형

배열 객체이지만 기본 클래스로 사용할 수없는 이유는 무엇입니까?


Java 언어 사양은 다음을 지정합니다.

Java 프로그래밍 언어에서 배열은 객체 (§4.3.1)이며 동적으로 생성되며 Object 유형 (§4.3.2)의 변수에 할당 될 수 있습니다. 클래스의 모든 메소드 Object는 배열에서 호출 될 수 있습니다.

그래서, 고려 배열 개체입니다 - 왜 자바 디자이너는 예를 들어, 상속 및 재정의를 허용하지 않는 결정을, 않았 toString()거나 equals()?

현재 구문은 기본 클래스와 같은 배열 익명 클래스를 만들 수 없습니다 것입니다,하지만 난 생각하지 않는다 자신의 결정에 대한 이유였다.


자바는 객체가 아닌 언어와 모든 것이 객체였던 당시 매우 느린 언어 사이의 절충안이었습니다 ( Smalltalk 에 대해 생각해보십시오 ).

더 최근의 언어에서도 배열 (및 일반적으로 맵)의 언어 수준에서 빠른 구조를 갖는 것이 전략적 목표로 간주됩니다. 대부분의 사람들은 배열에 대한 상속 가능한 객체의 무게를 좋아하지 않을 것이며 JVM이 JIT와 같이 발전하기 전에는 누구도 이것을 원하지 않았습니다.

그렇기 때문에 배열은 객체이지만 클래스 인스턴스로 설계되지 않았습니다 ( "객체는 클래스 인스턴스 또는 배열입니다" ). 배열에서 메서드를 재정의 할 수있는 기능을 갖는 것에는 거의 이점이 없을 것이며, 적용 할 올바른 메서드를 확인해야하는 필요성을 상쇄하기에 충분하지 않을 것입니다 (제 생각에는 균형을 맞추기에 충분하지 않습니다. 연산자를 재정의 할 때 발생하는 것과 유사한 코드 읽기의 어려움 증가).


저는 UNDER THE HOOD- JVM이 배열을 처리하는 방법에 대해 알아야 할 거의 모든 것을 설명하는 객체 및 배열 을 발견했습니다. JVM에서 배열은 우리가 익숙한 다른 객체와 달리 특수한 바이트 코드 로 처리 됩니다.

JVM 명령어 세트에서 모든 객체는 배열을 제외하고 동일한 opcode 세트로 인스턴스화되고 액세스됩니다 . Java에서 배열은 본격적인 객체 이며 Java 프로그램의 다른 객체와 마찬가지로 동적으로 생성됩니다. 배열 참조는 Object 유형에 대한 참조가 호출되는 모든 곳에서 사용할 수 있으며, Object의 모든 메서드는 배열에서 호출 될 수 있습니다. 그러나 Java 가상 머신에서 어레이는 특수한 바이트 코드로 처리됩니다 .

다른 객체와 마찬가지로 배열 은 지역 변수로 선언 할 수 없습니다 . 배열 참조 만 가능합니다. 배열 객체 자체에는 항상 기본 유형의 배열이나 객체 참조의 배열이 포함됩니다. 객체 배열을 선언하면 객체 참조 배열이 생성됩니다. 객체 자체는 new로 명시 적으로 생성되고 배열의 요소에 할당되어야합니다.

배열은 동적으로 생성 된 객체이며 동일한 유형의 (일정한) 수의 객체를 보유하는 컨테이너 역할을합니다. 배열이 다른 객체와 같지 않은 것처럼 보이므로 다르게 취급됩니다.


기사 를 지적하고 싶습니다 . 배열과 객체가 다른 opcode를 따르는 것처럼 보입니다. 솔직히 그 이상으로 요약 할 수는 없지만 배열은 Objects우리가 일반적으로 사용하는 것처럼 취급 되지 않으므로 Object메서드를 상속하지 않습니다 .

짧고 자세하게 읽을 수있는 매우 흥미로운 글이므로 해당 게시물의 작성자에게 전체 크레딧을 제공합니다.


여러 출처를 통해 주제를 더 파고 들자 이전 답변의 더 정교한 버전을 제공하기로 결정했습니다.

객체배열의 인스턴스화 는 JVM 내에서 매우 다르며 각각의 바이트 코드를 따릅니다.

목적:

Object인스턴스화 new는 두 개의 피연산자- indexbyte1& 의 조합 인 간단한 Opcode 따릅니다 indexbyte2. 인스턴스화되면 JVM 은이 개체에 대한 참조stack. 이것은 유형에 관계없이 모든 개체에 대해 발생합니다.


어레이 :

Array그러나 Opcode는 (배열의 인스턴스화와 관련 하여) 세 가지 다른 코드로 나뉩니다.

newarray -길이를 팝하고, 유형이 나타내는 유형의 기본 유형의 새 배열을 할당하고, 새 배열의 objectref를 푸시합니다.

newarrayopcode는 byte short char int long float double boolean객체 참조가 아닌 기본 데이터 유형 ( ) 을 포함하는 배열을 만들 때 사용됩니다 .

anewarray -길이를 팝하고 indexbyte1 및 indexbyte2로 표시된 클래스 객체의 새 배열을 할당하고 새 배열의 objectref를 푸시합니다.

anewarray opcode는 객체 참조 배열을 만들 때 사용됩니다.

multianewarray -배열 길이의 차원 수를 팝하고 indexbyte1 및 indexbyte2로 표시된 클래스의 새로운 다차원 배열을 할당하고 새 배열의 objectref를 푸시합니다.

multianewarray 다차원 배열을 할당 할 때 명령어가 사용됩니다.


객체 클래스 인스턴스 또는 배열 일 있습니다.

Oracle Docs 에서 가져 오기

클래스 인스턴스는 클래스 인스턴스 생성 표현식에 의해 명시 적으로 생성됩니다.

그러나

배열은 배열 생성 표현식에 의해 명시 적으로 생성됩니다.

이것은 opcode에 관한 정보와 함께 진행됩니다. 배열은 단순히 클래스 인터페이스로 개발되지 않고 대신 배열 생성 표현식에 의해 명시 적으로 생성되므로 자연스럽게 암시 적 으로 상속 및 / 또는 재정의 할 수 없습니다 Object.

우리가 보았 듯이, 배열이 원시 데이터 유형을 보유 할 수 있다는 사실과는 아무 관련이 없습니다. 비록 몇 가지 생각을 제공 한 후, 하나가 할 수 있습니다 상황 건너 매우 일반적인 아닙니다 toString()또는 equals()그러나 시도하고 대답 할 수있는 매우 흥미로운 질문은 여전히이었다.


자원:

Oracle-Docs 4.3.1 장

Oracle-Docs 15.10.1 장

Artima-UnderTheHood


표준 자바 라이브러리에는 하위 클래스를 만들 수없는 많은 클래스가 있으며 배열이 유일한 예는 아닙니다. 고려 String하거나 StringBuffer, 또는 "원시 래퍼 '의 같은 Integer, 또는 Double. JVM이 이러한 객체를 처리 할 때 이러한 객체의 정확한 구조를 아는 것을 기반으로하는 최적화가 있습니다 (예 : 기본 요소를 풀거나 바이트 수준에서 배열 메모리를 조작). 무엇이든 재정의 할 수 있다면 불가능하며 프로그램의 성능에 매우 나쁜 영향을 미칩니다.

참고 URL : https://stackoverflow.com/questions/27504925/why-are-arrays-objects-but-can-not-be-used-as-a-base-class

반응형