명확하고 간결하며 정확한 답변을 찾고 있습니다.
좋은 설명에 대한 링크는 환영하지만 실제 답변으로 이상적입니다.
language-but-not-type-agnostic
. static-language-agnostic
? 나는 그렇게 구별이 필요하다는 것을 확신하지 못한다. 메타에는 좋은 질문이 될 수 있습니다.
명확하고 간결하며 정확한 답변을 찾고 있습니다.
좋은 설명에 대한 링크는 환영하지만 실제 답변으로 이상적입니다.
language-but-not-type-agnostic
. static-language-agnostic
? 나는 그렇게 구별이 필요하다는 것을 확신하지 못한다. 메타에는 좋은 질문이 될 수 있습니다.
답변:
박스형 값은 기본 유형 * 주위의 최소 래퍼 인 데이터 구조 입니다 . 박스형 값은 일반적으로 힙의 객체에 대한 포인터로 저장됩니다 .
따라서 박스형 값은 더 많은 메모리를 사용하고 최소 두 개의 메모리 조회를 통해 액세스합니다. 한 번은 포인터를 가져오고 다른 한 번은 해당 포인터를 프리미티브로 따라갑니다. 분명히 이것은 당신이 당신의 내부 루프에서 원하는 종류의 것이 아닙니다. 반면, 박스형 값은 일반적으로 시스템의 다른 유형에서 더 잘 재생됩니다. 그것들은 언어의 일류 데이터 구조이기 때문에 다른 데이터 구조가 가지고있는 예상 메타 데이터와 구조를 가지고 있습니다.
Java 및 Haskell 일반 컬렉션에는 상자없는 값이 포함될 수 없습니다. .NET의 일반 컬렉션은 벌칙없이 상자에 넣지 않은 값을 보유 할 수 있습니다. Java의 제네릭이 컴파일 타임 유형 검사에만 사용되는 경우 .NET은 런타임에 인스턴스화 된 각 제네릭 유형에 대한 특정 클래스를 생성합니다 .
Java와 Haskell은 unboxed 배열을 가지고 있지만 다른 컬렉션보다 분명히 덜 편리합니다. 그러나 최고의 성능이 필요할 때 복싱 및 언 박싱의 오버 헤드를 피하는 것이 다소 불편합니다.
*이 논의에서 프리미티브 값은 힙의 값에 대한 포인터로 저장되는 것이 아니라 호출 스택 에 저장할 수있는 값입니다. 종종 그것은 기계 유형 (int, float 등), 구조체 및 때로는 정적 크기의 배열 일뿐입니다. .NET-land는이를 참조 형식과 달리 값 형식이라고합니다. 자바 사람들은 그것들을 원시 유형이라고 부릅니다. Haskellions는 박스형 박스라고 부릅니다.
** 나는이 답변에서 Java, Haskell 및 C #에도 중점을두고 있습니다. 그 가치가 있기 때문에 Python, Ruby 및 Javascript에는 모두 독점적으로 상자 값이 있습니다. 이것은 "모든 것이 객체입니다"접근 방식이라고도합니다.
***주의 사항 : 충분히 고급 컴파일러 / JIT는 실제로 소스를 볼 때 의미 적으로 상자에 넣은 값이 런타임에 상자에 넣지 않은 값일 수 있음을 실제로 감지 할 수 있습니다. 본질적으로, 훌륭한 언어 구현 자 덕분에 상자가 때로는 무료입니다.
에서 간단히 말해서 C # 3.0 :
복싱은 값 유형을 참조 유형으로 캐스팅하는 행위입니다.
int x = 9;
object o = x; // boxing the int
언 박싱은 ... 그 반대입니다 :
// unboxing o
object o = 9;
int x = (int)o;
복싱 및 언 박싱은 프리미티브 값을 객체 지향 래퍼 클래스로 변환하거나 (박싱), 객체 지향 래퍼 클래스에서 프리미티브 값으로 다시 변환하는 프로세스입니다 (unboxing).
예를 들어, 자바에서는 프리미티브를 객체에만 저장할 수 없기 때문에 int
값 Integer
을 저장 하려면 값을 (박싱) 으로 변환해야 할 수도 있습니다. 당신이이 밖으로 돌아 가야 할 때 당신은 같은 값 취득 할 수 있습니다 아닌 당신이 그것을 언 박싱 할 수 있도록합니다.Collection
Collection
Collection
int
Integer
복싱과 언 박싱은 본질적으로 나쁘지 는 않지만 트레이드 오프입니다. 언어 구현에 따라 프리미티브를 사용하는 것보다 속도가 느리고 메모리를 많이 사용할 수 있습니다. 그러나 더 높은 수준의 데이터 구조를 사용하고 코드의 유연성을 높일 수도 있습니다.
요즘에는 Java (및 다른 언어) "autoboxing / autounboxing"기능의 맥락에서 가장 일반적으로 논의됩니다. 다음은 오토 박싱에 대한 자바 중심 설명입니다 .
.Net에서 :
함수가 어떤 변수를 소비 할 것인지에 의존 할 수없는 경우가 많으므로 가장 낮은 공통 분모에서 확장되는 객체 변수를 사용해야합니다 object
.
그러나 object
클래스이며 그 내용을 참조로 저장합니다.
List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value
List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int
두 정보 모두 동일한 정보를 보유하지만 두 번째 목록은 더 크고 느립니다. 두 번째 목록의 각 값을 실제로 참조 인 object
보류를 int
.
이에 int
싸여 있기 때문에 boxed라고 합니다 object
. 캐스트 int
백시 박스가 해제되어 다시 값으로 변환됩니다.
값 유형 (예 : all structs
)의 경우 속도가 느리고 잠재적으로 더 많은 공간을 사용합니다.
참조 유형 (예 : all classes
)의 경우 어쨌든 참조로 저장되므로 문제가 훨씬 적습니다.
박스형 값 유형의 또 다른 문제는 값이 아니라 박스를 다루고 있는지 확실하지 않다는 것입니다. 두 개 structs
를 비교하면 값을 비교하지만 두 개 classes
를 비교 하면 (기본적으로) 참조를 비교합니다. 즉, 동일한 인스턴스입니까?
박스형 값 유형을 처리 할 때 혼동 될 수 있습니다.
int a = 7;
int b = 7;
if(a == b) // Evaluates to true, because a and b have the same value
object c = (object) 7;
object d = (object) 7;
if(c == d) // Evaluates to false, because c and d are different instances
해결하기 쉽습니다.
if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals
if(((int) c) == ((int) d)) // Evaluates to true once the values are cast
그러나 상자 값을 처리 할 때주의해야 할 또 다른 사항입니다.
Object
하고 등식 연산자를 구현하지는 않지만 클래스 유형은 Is
연산자 와 비교할 수 있습니다 . 반대로 Int32
항등 연산자와 함께 사용할 수는 있지만 사용할 수는 없습니다 Is
. 이러한 구별을 통해 어떤 유형의 비교가 수행되고 있는지 훨씬 명확하게 알 수 있습니다.
.NET FCL 일반 컬렉션 :
List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>
이전 컬렉션 구현에서 boxing 및 unboxing의 성능 문제를 극복하도록 설계되었습니다.
자세한 내용은 16 장 C # (2 판)을 통한 CLR을 참조하십시오 .
복싱 및 언 박싱은 가치 유형이 객체로 취급 될 수 있도록합니다. 복싱은 값을 개체 참조 유형의 인스턴스로 변환하는 것을 의미합니다. 예를 들어, Int
클래스이며 int
데이터 유형입니다. 로 변환 int
하는 Int
것은 복싱의 예시이며,로 변환 Int
하는 int
것은 언 박싱입니다. 반면이 개념은 가비지 수집에 도움이됩니다. Unboxing은 객체 유형을 값 유형으로 변환합니다.
int i=123;
object o=(object)i; //Boxing
o=123;
i=(int)o; //Unboxing.
var ii = 123; typeof ii
반환합니다 number
. var iiObj = new Number(123); typeof iiObj
을 반환합니다 object
. typeof ii + iiObj
을 반환합니다 number
. 그래서 이것은 권투와 같은 자바 스크립트입니다. iiObj 값은 산술을 수행하고 상자없는 값을 반환하기 위해 자동으로 기본 숫자 (상자없는)로 변환되었습니다.
다른 방법과 마찬가지로 오토 박싱은주의해서 사용하지 않으면 문제가 될 수 있습니다. 고전은 NullPointerException으로 끝나고 추적 할 수 없습니다. 디버거에서도 마찬가지입니다. 이 시도:
public class TestAutoboxNPE
{
public static void main(String[] args)
{
Integer i = null;
// .. do some other stuff and forget to initialise i
i = addOne(i); // Whoa! NPE!
}
public static int addOne(int i)
{
return i + 1;
}
}
i
가 조기에 초기화되었습니다. Integer i;
컴파일러가 초기화를 잊었 음을 가리킬 수 있도록 빈 선언 ( )으로 지정하거나 값을 알 때까지 선언을 기다립니다.