원시 유형은 무엇이며 왜 사용하지 않아야합니까?
질문 :
- Java의 원시 유형은 무엇이며 새 코드에서 사용해서는 안된다는 말을 자주 듣는 이유는 무엇입니까?
- 원시 유형을 사용할 수없는 경우 대안은 무엇이며 어떻게 더 나은가요?
원시 유형이란 무엇입니까?
Java 언어 사양은 다음과 같이 원시 유형 을 정의 합니다.
JLS 4.8 원시 유형
원시 유형은 다음 중 하나로 정의됩니다.
수반되는 형식 인수 목록없이 제네릭 형식 선언의 이름을 사용하여 형성되는 참조 형식입니다.
요소 유형이 원시 유형 인 배열 유형입니다.
의 슈퍼 클래스 또는 슈퍼 인터페이스에서 상속되지 않는
static
원시 형식의 멤버R
가 아닌 형식 입니다R
.
다음은 설명을위한 예입니다.
public class MyType<E> {
class Inner { }
static class Nested { }
public static void main(String[] args) {
MyType mt; // warning: MyType is a raw type
MyType.Inner inn; // warning: MyType.Inner is a raw type
MyType.Nested nest; // no warning: not parameterized type
MyType<Object> mt1; // no warning: type parameter given
MyType<?> mt2; // no warning: type parameter given (wildcard OK!)
}
}
여기서, MyType<E>
A는 파라미터 화 된 형태 ( JLS 4.5 ). 이 유형을 간단히 MyType
줄여서 구어체로 언급하는 것이 일반적 이지만 기술적으로 이름은 MyType<E>
입니다.
mt
위의 정의에서 첫 번째 글 머리 기호에 의해 원시 유형 (및 컴파일 경고 생성)이 있습니다. inn
또한 세 번째 글 머리 기호에 원시 유형이 있습니다.
MyType.Nested
이 파라미터 화 된 형태의 멤버 유형에도 불구하고, 매개 변수화 된 유형이 아닌 MyType<E>
그 때문에, static
.
mt1
, 및 mt2
둘 다 실제 유형 매개 변수로 선언되므로 원시 유형이 아닙니다.
원시 유형의 특별한 점은 무엇입니까?
기본적으로 원시 유형은 제네릭이 도입되기 전처럼 작동합니다. 즉, 다음은 컴파일 타임에 완전히 합법적입니다.
List names = new ArrayList(); // warning: raw type!
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // not a compilation error!
위의 코드는 정상적으로 실행되지만 다음도 있다고 가정합니다.
for (Object o : names) {
String name = (String) o;
System.out.println(name);
} // throws ClassCastException!
// java.lang.Boolean cannot be cast to java.lang.String
이제 우리는 런타임에 문제가 발생 names
합니다 instanceof String
..
당신이 원하는 경우 아마도 names
에만 포함 String
, 당신은 할 수 아마도 여전히 원시 형식을 사용하고 모든 확인 수동으로 add
자신을 한 후 수동으로 주조 에 String
에서 모든 항목 names
. 더 좋은 점 은 원시 유형을 사용하지 않고 컴파일러가 Java 제네릭의 힘을 활용하여 모든 작업을 수행하도록하는 것입니다 .
List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // compilation error!
당신이 경우 물론, DO 원하는 names
수 있도록 Boolean
, 당신은 그것을 선언 할 수 있습니다 List<Object> names
, 그리고 위의 코드를 컴파일합니다.
또한보십시오
How's a raw type different from using <Object>
as type parameters?
The following is a quote from Effective Java 2nd Edition, Item 23: Don't use raw types in new code:
원시 유형
List
과 매개 변수화 된 유형 의 차이점은 무엇List<Object>
입니까? 느슨하게 말하면 전자는 제네릭 유형 검사를 옵트 아웃 한 반면 후자는 컴파일러에게 모든 유형의 객체를 보유 할 수 있다고 명시 적으로 말했습니다.List<String>
를 유형의 매개 변수에 전달할 수는 있지만 유형의 매개 변수List
에는 전달할 수 없습니다List<Object>
. 제네릭에 대한 하위 유형 규칙List<String>
이 있으며 원시 유형의 하위 유형List
이지만 매개 변수화 된 유형이 아닙니다List<Object>
. 결과적으로 와 같은 원시 유형을 사용하는 경우 유형 안전성이 손실List
되지만List<Object>
.
점을 설명하기 위해, 소요 다음과 같은 방법을 고려 List<Object>
하고를 추가를 new Object()
.
void appendNewObject(List<Object> list) {
list.add(new Object());
}
Java의 제네릭은 변하지 않습니다. A List<String>
가 아니므로 List<Object>
다음은 컴파일러 경고를 생성합니다.
List<String> names = new ArrayList<String>();
appendNewObject(names); // compilation error!
appendNewObject
원시 유형 List
을 매개 변수 로 사용하도록 선언 한 경우 이는 컴파일되므로 제네릭에서 얻은 유형 안전성을 잃게됩니다.
또한보십시오
원시 유형 <?>
은 유형 매개 변수로 사용하는 것과 어떻게 다릅니 까?
List<Object>
, List<String>
등은 모두 List<?>
이므로 List
대신에 있다고 말하고 싶을 수 있습니다 . 그러나 큰 차이점이 있습니다. a List<E>
는 정의 만하기 때문에 add(E)
임의의 객체를 List<?>
. 원시 타입이 있기 때문에 다른 한편으로는, List
형태의 안전성이 없습니다, 당신은 할 수있는 add
단지에 대해서는 아무것도 List
.
이전 스 니펫의 다음 변형을 고려하십시오.
static void appendNewObject(List<?> list) {
list.add(new Object()); // compilation error!
}
//...
List<String> names = new ArrayList<String>();
appendNewObject(names); // this part is fine!
컴파일러는 List<?>
! 의 유형 불변성을 잠재적으로 위반하지 않도록 보호하는 멋진 작업을 수행했습니다 . 매개 변수를 원시 유형으로 선언 List list
한 경우 코드가 컴파일되고 유형 불변을 위반합니다 List<String> names
.
원시 유형은 해당 유형의 삭제입니다.
JLS 4.8로 돌아 가기 :
이 형태로 사용하는 것이 가능하다 소거 파라미터 화 된 형태 또는 유형의 소자 파라미터 화 된 형태 인 어레이 형의 소거한다. 이러한 유형을 원시 유형 이라고합니다 .
[...]
원시 유형의 수퍼 클래스 (각각 수퍼 인터페이스)는 제네릭 유형의 매개 변수화에 대한 수퍼 클래스 (수퍼 인터페이스)를 삭제 한 것입니다.
생성자, 인스턴스 메서드 또는 수퍼 클래스 또는 수퍼 인터페이스에서 상속되지 않는
static
원시 유형의 필드C
가 아닌 유형은에 해당하는 제네릭 선언에서 해당 유형의 삭제에 해당하는 원시 유형입니다C
.
간단히 말해서 원시 유형이 사용되면 생성자, 인스턴스 메서드 및 비 static
필드 도 지워 집니다.
다음 예를 살펴보십시오.
class MyType<E> {
List<String> getNames() {
return Arrays.asList("John", "Mary");
}
public static void main(String[] args) {
MyType rawType = new MyType();
// unchecked warning!
// required: List<String> found: List
List<String> names = rawType.getNames();
// compilation error!
// incompatible types: Object cannot be converted to String
for (String str : rawType.getNames())
System.out.print(str);
}
}
우리는 원료를 사용하는 경우 MyType
, getNames
그것은 원시를 반환 그래서 잘으로 삭제된다 List
!
JLS 4.6 은 계속해서 다음을 설명합니다.
형식 삭제는 또한 생성자 또는 메서드의 서명을 매개 변수가있는 형식이나 형식 변수가없는 서명에 매핑합니다. 생성자 또는 메서드 서명 의 삭제는에 제공된 모든 형식 매개 변수 유형의 삭제와
s
동일한 이름으로 구성된 서명s
입니다s
.메서드 또는 생성자의 서명이 지워지면 메서드의 반환 형식과 제네릭 메서드 또는 생성자의 형식 매개 변수도 지워집니다.
제네릭 메서드의 서명 지우기에는 형식 매개 변수가 없습니다.
다음 버그 보고서에는 컴파일러 개발자 인 Maurizio Cimadamore와 JLS 작성자 중 한 명인 Alex Buckley가 이러한 종류의 동작이 발생해야하는 이유에 대한 몇 가지 생각이 포함되어 있습니다. https://bugs.openjdk.java.net/browse / JDK-6400189 . (요약하면 사양이 더 간단 해집니다.)
안전하지 않은 경우 원시 유형을 사용할 수있는 이유는 무엇입니까?
다음은 JLS 4.8의 또 다른 인용문입니다.
원시 유형의 사용은 레거시 코드의 호환성에 대한 양보로만 허용됩니다. Java 프로그래밍 언어에 일반성을 도입 한 후 작성된 코드에서 원시 유형을 사용하는 것은 권장되지 않습니다. Java 프로그래밍 언어의 향후 버전에서는 원시 유형의 사용을 허용하지 않을 수 있습니다.
유효한 Java 2nd Edition 에는 다음을 추가해야합니다.
원시 유형을 사용해서는 안된다는 점을 감안할 때 언어 디자이너가 허용 한 이유는 무엇입니까? 호환성을 제공합니다.
Java 플랫폼은 제네릭이 도입 된 20 년이되었을 때 제네릭을 사용하지 않는 엄청난 양의 Java 코드가 존재했습니다. 이 모든 코드가 제네릭을 사용하는 새로운 코드와 합법적이고 상호 운용 가능한 상태로 유지되는 것이 중요하다고 간주되었습니다. 매개 변수화 된 유형의 인스턴스를 일반 유형과 함께 사용하도록 설계된 메서드에 전달하는 것은 합법적이어야하며 그 반대의 경우도 마찬가지입니다. 마이그레이션 호환성 이라고하는이 요구 사항으로 인해 원시 유형을 지원하기로 결정되었습니다.
요약하면, 원시 유형은 새 코드에서 절대 사용해서는 안됩니다. 항상 매개 변수화 된 유형을 사용해야합니다 .
예외가 없습니까?
불행히도 Java 제네릭은 수정되지 않았기 때문에 새 코드에서 원시 유형을 사용해야하는 두 가지 예외가 있습니다.
- 클래스 리터럴, 예 :
List.class
notList<String>.class
instanceof
피연산자, 예 :o instanceof Set
noto instanceof Set<String>
또한보십시오
Java의 원시 유형은 무엇이며 새 코드에서 사용해서는 안된다는 말을 자주 듣는 이유는 무엇입니까?
원시 유형은 Java 언어의 고대 역사입니다. 처음에는 거기에 있었고 Collections
그들은 Objects
그 이상도 그 이하도 아무것도 가지고 있지 않았습니다. 에 모든 작업 Collections
에서 필요한 캐스트 Object
원하는 유형.
List aList = new ArrayList();
String s = "Hello World!";
aList.add(s);
String c = (String)aList.get(0);
이것은 대부분의 경우 작동했지만 오류가 발생했습니다.
List aNumberList = new ArrayList();
String one = "1";//Number one
aNumberList.add(one);
Integer iOne = (Integer)aNumberList.get(0);//Insert ClassCastException here
이전 유형없는 컬렉션은 유형 안전성을 적용 할 수 없으므로 프로그래머는 컬렉션에 저장 한 내용을 기억해야했습니다.
이 제한을 피하기 위해 고안된 제네릭은 개발자가 저장된 유형을 한 번 선언하고 컴파일러가 대신이를 수행합니다.
List<String> aNumberList = new ArrayList<String>();
aNumberList.add("one");
Integer iOne = aNumberList.get(0);//Compile time error
String sOne = aNumberList.get(0);//works fine
비교하려고:
// Old style collections now known as raw types
List aList = new ArrayList(); //Could contain anything
// New style collections with Generics
List<String> aList = new ArrayList<String>(); //Contains only Strings
더 복잡한 Compareable 인터페이스 :
//raw, not type save can compare with Other classes
class MyCompareAble implements CompareAble
{
int id;
public int compareTo(Object other)
{return this.id - ((MyCompareAble)other).id;}
}
//Generic
class MyCompareAble implements CompareAble<MyCompareAble>
{
int id;
public int compareTo(MyCompareAble other)
{return this.id - other.id;}
}
원시 유형으로 CompareAble
인터페이스 를 구현하는 것은 불가능합니다 compareTo(MyCompareAble)
. 사용하지 말아야하는 이유 :
- 에
Object
저장된 모든Collection
것은 사용하기 전에 캐스트해야합니다. - 제네릭을 사용하면 컴파일 시간을 확인할 수 있습니다.
- 원시 유형을 사용하는 것은 각 값을 다음과 같이 저장하는 것과 같습니다.
Object
컴파일러의 기능 : 제네릭은 이전 버전과 호환되며 원시 유형과 동일한 Java 클래스를 사용합니다. 마술은 대부분 컴파일 시간에 발생합니다.
List<String> someStrings = new ArrayList<String>();
someStrings.add("one");
String one = someStrings.get(0);
다음과 같이 컴파일됩니다.
List someStrings = new ArrayList();
someStrings.add("one");
String one = (String)someStrings.get(0);
이것은 원시 유형을 직접 사용한 경우 작성하는 것과 동일한 코드입니다. CompareAble
인터페이스에서 무슨 일이 일어나는지 잘 모르겠지만 compareTo
하나는 a MyCompareAble
를 취하고 다른 하나는 an을 취하고 Object
그것을 캐스팅 한 후 첫 번째로 전달하는 두 가지 함수를 생성한다고 생각 합니다.
원시 유형의 대안 : 제네릭 사용
원시 유형은 유형 인수가없는 일반 클래스 또는 인터페이스의 이름입니다. 예를 들어, 일반적인 Box 클래스는 다음과 같습니다.
public class Box<T> {
public void set(T t) { /* ... */ }
// ...
}
의 매개 변수화 된 유형을 만들려면 Box<T>
형식 유형 매개 변수에 대한 실제 유형 인수를 제공합니다 T
.
Box<Integer> intBox = new Box<>();
실제 유형 인수가 생략되면 원시 유형을 만듭니다 Box<T>
.
Box rawBox = new Box();
따라서 Box
제네릭 유형의 원시 유형입니다 Box<T>
. 그러나 제네릭이 아닌 클래스 또는 인터페이스 유형은 원시 유형이 아닙니다.
많은 API 클래스 (예 : Collections 클래스)가 JDK 5.0 이전에는 일반적이지 않았기 때문에 원시 유형이 레거시 코드에 표시됩니다. 원시 유형을 사용하는 경우, 당신은 기본적으로 사전 제네릭 동작을 얻을 - A는 Box
당신이 제공 Object
에요. 이전 버전과의 호환성을 위해 매개 변수화 된 유형을 원시 유형에 할당 할 수 있습니다.
Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK
그러나 매개 변수화 된 유형에 원시 유형을 할당하면 경고가 표시됩니다.
Box rawBox = new Box(); // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox; // warning: unchecked conversion
원시 유형을 사용하여 해당 제네릭 유형에 정의 된 제네릭 메서드를 호출하는 경우에도 경고가 표시됩니다.
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // warning: unchecked invocation to set(T)
경고는 원시 유형이 제네릭 유형 검사를 우회하여 안전하지 않은 코드 포착을 런타임으로 연기 함을 보여줍니다. 따라서 원시 유형을 사용하지 않아야합니다.
Type Erasure 섹션에는 Java 컴파일러가 원시 유형을 사용하는 방법에 대한 자세한 정보가 있습니다.
확인되지 않은 오류 메시지
앞서 언급했듯이 레거시 코드를 일반 코드와 혼합하면 다음과 유사한 경고 메시지가 표시 될 수 있습니다.
참고 : Example.java는 확인되지 않거나 안전하지 않은 작업을 사용합니다.
참고 : 자세한 내용은 -Xlint : unchecked로 다시 컴파일하십시오.
이는 다음 예제와 같이 원시 유형에서 작동하는 이전 API를 사용할 때 발생할 수 있습니다.
public class WarningDemo {
public static void main(String[] args){
Box<Integer> bi;
bi = createBox();
}
static Box createBox(){
return new Box();
}
}
"확인되지 않음"이라는 용어는 컴파일러에 형식 안전성을 보장하는 데 필요한 모든 형식 검사를 수행 할 수있는 충분한 형식 정보가 없음을 의미합니다. 컴파일러가 힌트를 제공하지만 "확인되지 않음"경고는 기본적으로 비활성화됩니다. "확인되지 않은"경고를 모두 보려면 -Xlint : unchecked로 다시 컴파일하십시오.
-Xlint : unchecked로 이전 예제를 다시 컴파일하면 다음과 같은 추가 정보가 표시됩니다.
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found : Box
required: Box<java.lang.Integer>
bi = createBox();
^
1 warning
확인되지 않은 경고를 완전히 비활성화하려면 -Xlint : -unchecked 플래그를 사용하십시오. @SuppressWarnings("unchecked")
주석은 확인 경고를 억제한다. @SuppressWarnings
구문에 익숙하지 않은 경우 주석을 참조하십시오.
원본 출처 : Java Tutorials
private static List<String> list = new ArrayList<String>();
유형 매개 변수를 지정해야합니다.
경고는 제네릭 을 지원하도록 정의 된 유형이 원시 형식을 사용하는 대신 매개 변수화되어야 함 을 알려 줍니다.
List
제네릭을 지원하도록 정의되었습니다 : public class List<E>
. 이렇게하면 컴파일 타임에 확인되는 많은 형식 안전 작업이 허용됩니다.
Java의 "원시"유형은 유형이 안전한 제네릭 유형 매개 변수가 아니라 비 일반적이고 "원시"객체를 다루는 클래스입니다.
예를 들어, Java 제네릭을 사용할 수 있기 전에 다음과 같은 컬렉션 클래스를 사용합니다.
LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);
객체를 목록에 추가 할 때 어떤 유형의 객체인지 상관하지 않으며 목록에서 가져올 때 예상 한 유형으로 명시 적으로 캐스팅해야합니다.
제네릭을 사용하면 목록에 들어갈 수있는 객체 유형을 명시 적으로 지정해야하므로 "알 수 없음"요소를 제거합니다.
LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);
제네릭을 사용하면 get 호출에서 오는 객체를 캐스팅 할 필요가 없으며 컬렉션은 MyObject에서만 작동하도록 미리 정의되어 있습니다. 바로이 사실이 제네릭의 주요 원동력입니다. 런타임 오류의 원인을 컴파일 타임에 확인할 수있는 것으로 변경합니다.
원시 유형은 무엇이며 새 코드에서 사용해서는 안된다는 말을 자주 듣는 이유는 무엇입니까?
"원시 유형"은 매개 변수화 된 유형에 대한 유형 인수를 지정하지 않고 일반 클래스를 사용하는 List
것입니다 List<String>
. 예를 들어 . 제네릭이 Java에 도입되었을 때 제네릭을 사용하도록 여러 클래스가 업데이트되었습니다. 이러한 클래스를 "원시 유형"(유형 인수를 지정하지 않음)으로 사용하면 레거시 코드를 계속 컴파일 할 수 있습니다.
"원시 유형"은 이전 버전과의 호환성을 위해 사용됩니다. 유형 인수와 함께 제네릭 클래스를 사용하면 더 강력한 타이핑이 가능 해져 코드 이해도가 향상되고 잠재적 인 문제를 더 일찍 발견 할 수 있으므로 새 코드에서 사용하지 않는 것이 좋습니다.
원시 유형을 사용할 수없는 경우 대안은 무엇이며 어떻게 더 나은가요?
선호되는 대안은 적절한 유형 인수 (예 :)와 함께 제네릭 클래스를 의도 한대로 사용하는 것 List<String>
입니다. 이를 통해 프로그래머는 유형을보다 구체적으로 지정할 수 있고, 향후 유지 관리자에게 변수 또는 데이터 구조의 의도 된 사용에 대해 더 많은 의미를 전달할 수 있으며 컴파일러가 더 나은 유형 안전성을 적용 할 수 있습니다. 이러한 장점은 함께 코드 품질을 향상시키고 일부 코딩 오류의 도입을 방지하는 데 도움이됩니다.
예를 들어, 프로그래머가 'names'라는 List 변수에 문자열 만 포함되도록하려는 메서드의 경우 :
List<String> names = new ArrayList<String>();
names.add("John"); // OK
names.add(new Integer(1)); // compile error
컴파일러는 다음과 같이 작성하기를 원합니다.
private static List<String> list = new ArrayList<String>();
그렇지 않으면 원하는 유형을에 추가 list
하여 인스턴스화를 new ArrayList<String>()
무의미 하게 만들 수 있기 때문 입니다. Java 제네릭은 컴파일 타임 기능 일 뿐이므로로 생성 된 객체 는 "원시 유형"의 참조에 할당 된 경우 new ArrayList<String>()
기꺼이 Integer
또는 JFrame
요소를 수락 List
합니다. 객체 자체는 포함해야하는 유형에 대해 아무것도 모르고 컴파일러 만 수행합니다.
여기서는 개념을 명확히 할 수있는 여러 사례를 고려하고 있습니다.
1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();
사례 1
ArrayList<String> arr
ArrayList
유형 String
의 ArralyList
객체 를 참조하는 유형 의 참조 변수입니다 String
. 이는 String 유형 Object 만 보유 할 수 있음을 의미합니다.
String
Raw 유형 이 아닌 것이 엄격 하므로 경고를 발생시키지 않습니다.
arr.add("hello");// alone statement will compile successfully and no warning.
arr.add(23); //prone to compile time error.
//error: no suitable method found for add(int)
사례 2
이 경우 ArrayList<String> arr
엄격한 유형이지만 Object new ArrayList();
는 원시 유형입니다.
arr.add("hello"); //alone this compile but raise the warning.
arr.add(23); //again prone to compile time error.
//error: no suitable method found for add(int)
여기 arr
에 엄격한 유형이 있습니다. 따라서 integer
.
경고 :-
Raw
유형 객체가의Strict
유형 참조 변수를 참조ArrayList
합니다.
사례 3
이 경우 ArrayList arr
원시 유형이지만 객체 new ArrayList<String>();
는 엄격한 유형입니다.
arr.add("hello");
arr.add(23); //compiles fine but raise the warning.
arr
원시 유형 이므로 모든 유형의 객체를 추가합니다 .
경고 :-
Strict
유형 개체가raw
유형 참조 변수를 참조합니다.
원시 타입은의는 A의 부족 유형 매개 변수 제네릭 형식을 사용하는 경우.
원시 유형은 s의 double
a Set
에 삽입하는 것과 같은 런타임 오류를 일으킬 수 있으므로 사용해서는 안됩니다 int
.
Set set = new HashSet();
set.add(3.45); //ok
에서 항목을 검색 할 때 Set
무엇이 나오는지 알 수 없습니다. 모든 것이 int
s 일 것으로 예상하고 다음으로 캐스팅 한다고 가정합니다 Integer
. double
3.45가 나오면 런타임에 예외가 발생합니다 .
A의 유형 매개 변수 귀하의 추가 Set
, 한 번에 컴파일 오류가 발생합니다. 이 선점 형 오류를 사용하면 런타임 중에 문제가 발생하기 전에 문제를 해결할 수 있으므로 시간과 노력이 절약됩니다.
Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.
원시 유형이 당신을 물릴 또 다른 경우가 있습니다.
public class StrangeClass<T> {
@SuppressWarnings("unchecked")
public <X> X getSomethingElse() {
return (X)"Testing something else!";
}
public static void main(String[] args) {
final StrangeClass<String> withGeneric = new StrangeClass<>();
final StrangeClass withoutGeneric = new StrangeClass();
final String value1,
value2;
// Compiles
value1 = withGeneric.getSomethingElse();
// Produces compile error:
// incompatible types: java.lang.Object cannot be converted to java.lang.String
value2 = withoutGeneric.getSomethingElse();
}
}
수락 된 답변에서 언급했듯이 원시 유형의 코드 내에서 제네릭에 대한 모든 지원을 잃습니다. 모든 유형 매개 변수는 삭제로 변환됩니다 (위의 예에서는 Object
).
무엇을 말하는 것은 당신의 것입니다 list
A는 List
unespecified 객체. 즉, Java는 목록에 어떤 종류의 개체가 있는지 알지 못합니다. 그런 다음 목록을 반복하려면 모든 요소를 캐스트해야 해당 요소의 속성 (이 경우 String)에 액세스 할 수 있습니다.
일반적으로 컬렉션을 매개 변수화하는 것이 더 나은 아이디어이므로 변환 문제가 발생하지 않고 매개 변수화 된 유형의 요소 만 추가 할 수 있으며 편집기는 적절한 선택 방법을 제공합니다.
private static List<String> list = new ArrayList<String>();
튜토리얼 페이지 .
원시 유형은 유형 인수가없는 일반 클래스 또는 인터페이스의 이름입니다. 예를 들어, 일반적인 Box 클래스는 다음과 같습니다.
public class Box<T> {
public void set(T t) { /* ... */ }
// ...
}
매개 변수화 된 유형의 Box를 만들려면 형식 유형 매개 변수 T에 실제 유형 인수를 제공합니다.
Box<Integer> intBox = new Box<>();
실제 유형 인수가 생략되면 원시 유형의 Box를 만듭니다.
Box rawBox = new Box();
샘플 연습을하고 똑같은 퍼즐을 풀고 나서이 페이지를 찾았습니다.
============== 샘플에서 제공하는 코드에서 나왔습니다 ==============
public static void main(String[] args) throws IOException {
Map wordMap = new HashMap();
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
countWord(wordMap, args[i]);
}
} else {
getWordFrequency(System.in, wordMap);
}
for (Iterator i = wordMap.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
System.out.println(entry.getKey() + " :\t" + entry.getValue());
}
=====================이 코드에 =======================
public static void main(String[] args) throws IOException {
// replace with TreeMap to get them sorted by name
Map<String, Integer> wordMap = new HashMap<String, Integer>();
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
countWord(wordMap, args[i]);
}
} else {
getWordFrequency(System.in, wordMap);
}
for (Iterator<Entry<String, Integer>> i = wordMap.entrySet().iterator(); i.hasNext();) {
Entry<String, Integer> entry = i.next();
System.out.println(entry.getKey() + " :\t" + entry.getValue());
}
}
================================================ ============================
더 안전 할 수도 있지만 철학을 깨뜨리는 데 4 시간이 걸렸습니다 ...
원시 유형을 피하십시오
원시 유형은 유형 매개 변수를 지정하지 않고 제네릭 유형을 사용하는 것을 말합니다.
예를 들어 ,
목록은 원시 유형이고 List<String>
매개 변수화 된 유형입니다.
제네릭이 JDK 1.5에 도입되었을 때 원시 유형은 이전 버전의 Java와의 하위 호환성을 유지하기 위해서만 유지되었습니다. 원시 유형을 사용하는 것은 여전히 가능하지만
피해야합니다 .
- 보통 캐스트가 필요합니다.
- 형식에 안전하지 않으며 일부 중요한 유형의 오류는 런타임에만 나타납니다.
그들은 덜 표현하고, 매개 변수 유형과 같은 방식으로 자기 문서를하지 않는 예
import java.util.*; public final class AvoidRawTypes { void withRawType() { //Raw List doesn't self-document, //doesn't state explicitly what it can contain List stars = Arrays.asList("Arcturus", "Vega", "Altair"); Iterator iter = stars.iterator(); while (iter.hasNext()) { String star = (String) iter.next(); //cast needed log(star); } } void withParameterizedType() { List < String > stars = Arrays.asList("Spica", "Regulus", "Antares"); for (String star: stars) { log(star); } } private void log(Object message) { System.out.println(Objects.toString(message)); } }
참고 : https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html
원시 유형은 표현하려는 것을 표현할 때 좋습니다.
예를 들어 역 직렬화 함수는를 반환 할 수 List
있지만 목록의 요소 유형을 알지 못합니다. 그래서 List
여기에 적절한 반환 형식이다.
참고 URL : https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it
'Nice programing' 카테고리의 다른 글
로컬 Git 변경 사항을 제거하는 다양한 방법 (0) | 2020.10.02 |
---|---|
PHP 구문 분석 / 구문 오류; (0) | 2020.10.02 |
SQL 조인 : where 절 대 on 절 (0) | 2020.10.02 |
pg_config 실행 파일을 찾을 수 없습니다. (0) | 2020.10.02 |
iOS 8에서 작동하지 않는 위치 서비스 (0) | 2020.10.02 |