차이점은 무엇입니까? Java 제네릭의 Object?
Java 제네릭을 올바르게 사용하기 위해 일부 코드를 정리할 수 있도록 Eclipse를 사용하고 있습니다. 대부분 유추 유형의 훌륭한 작업을 수행하지만 유추 유형이 가능한 한 일반적인 경우가 있습니다. Object. 그러나 Eclipse는 Object 유형과 '?'유형 중에서 선택할 수있는 옵션을 제공하는 것 같습니다.
차이점은 무엇입니까?
HashMap<String, ?> hash1;
과
HashMap<String, Object> hash2;
HashMap<String, String>
일치 Map<String, ?>
하지만 일치 하지 않는 인스턴스 Map<String, Object>
. String
s에서 무엇이든에 대한 맵을 허용하는 메소드를 작성한다고 가정하십시오 .
public void foobar(Map<String, Object> ms) {
...
}
을 (를) 제공 할 수 없습니다 HashMap<String, String>
. 당신이 쓰는 경우
public void foobar(Map<String, ?> ms) {
...
}
효과가있다!
Java의 제네릭에서 때때로 잘못 이해되는 List<String>
것은의 하위 유형이 아니라는 것입니다 List<Object>
. (그러나 String[]
실제로의 하위 유형은 Object[]
제네릭과 배열이 잘 혼합되지 않는 이유 중 하나입니다 (Java의 배열은 공변량이고 제네릭은 변하지 않습니다 )).
샘플 : 당신이 받아들이는 방법을 쓰고 싶다면 List
의의 InputStream
의와의 하위 유형 InputStream
, 당신은 쓸 것
public void foobar(List<? extends InputStream> ms) {
...
}
그런데 Joshua Bloch의 Effective Java 는 Java에서 그렇게 간단하지 않은 것을 이해하고 싶을 때 훌륭한 리소스입니다. (위의 질문은이 책에서도 잘 설명되어 있습니다.)
이 문제를 생각하는 또 다른 방법은
HashMap<String, ?> hash1;
에 해당
HashMap<String, ? extends Object> hash1;
이 지식을 Java Generics and Collections의 섹션 2.4의 "Get and Put Principle"과 결합하십시오 .
Get and Put Principle : 구조에서 값을 가져올 때만 확장 와일드 카드를 사용하고 구조에 값을 넣을 때는 슈퍼 와일드 카드를 사용하고 가져오고 넣을 때 와일드 카드를 사용하지 마십시오.
와일드 카드가 더 이해하기 쉬울 것입니다.
그것이 Collection<Object>
유형의 객체를 포함하는 일반 콜렉션 Object
이지만 Collection<?>
모든 유형의 콜렉션의 수퍼 유형 이라는 것을 기억하면 쉽게 이해할 수 있습니다 .
Map<String, ?>
값이 어떤 유형인지 알지 못하므로 에 아무 것도 넣을 수 없습니다 .
Map<String, Object>
값이로 알려져 있으므로 모든 객체를에 넣을 수 있습니다 Object
.
공분산 위의 답변은 대부분의 경우에 적용되지만 한 가지는 누락됩니다.
"?" 클래스 계층 구조에 "Object"를 포함합니다. String은 Object의 유형이고 Object는?의 유형이라고 말할 수 있습니다. 모든 것이 Object와 일치하는 것은 아니지만 모든 것이?와 일치합니다.
int test1(List<?> l) {
return l.size();
}
int test2(List<Object> l) {
return l.size();
}
List<?> l1 = Lists.newArrayList();
List<Object> l2 = Lists.newArrayList();
test1(l1); // compiles because any list will work
test1(l2); // compiles because any list will work
test2(l1); // fails because a ? might not be an Object
test2(l2); // compiled because Object matches Object
변수 로 키 의 값과 모든 유형의 값을 가질 수 있음을 선언 hash1
으로 선언 합니다.HashMap<String, ?>
hash1
HashMap
String
HashMap<String, ?> map;
map = new HashMap<String, Integer>();
map = new HashMap<String, Object>();
map = new HashMap<String, String>();
변수 map
가 해시 맵을 저장할 수 있으므로 위의 모든 것이 유효 합니다. 해당 변수는 보유하고있는 해시 맵의 값 유형이 무엇인지 상관하지 않습니다.
와일드 카드를 갖는 않습니다 되지 그러나, 당신은지도에 모든 유형의 개체를 만들어 보자. 사실, 위의 해시 맵을 사용하면 map
변수를 사용하여 아무것도 넣을 수 없습니다 .
map.put("A", new Integer(0));
map.put("B", new Object());
map.put("C", "Some String");
All of the above method calls will result in a compile-time error because Java doesn't know what the Value type of the HashMap inside map
is.
You can still get a value out of the hash map. Although you "don't know the value's type," (because you don't know what type of hash map is inside your variable), you can say that everything is a subclass of Object
and, so, whatever you get out of the map will be of the type Object:
HashMap<String, Integer> myMap = new HashMap<>();// This variable is used to put things into the map.
myMap.put("ABC", 10);
HashMap<String, ?> map = myMap;
Object output = map.get("ABC");// Valid code; Object is the superclass of everything, (including whatever is stored our hash map).
System.out.println(output);
The above block of code will print 10 to the console.
So, to finish off, use a HashMap
with wildcards when you do not care (i.e., it does not matter) what the types of the HashMap
are, for example:
public static void printHashMapSize(Map<?, ?> anyMap) {
// This code doesn't care what type of HashMap is inside anyMap.
System.out.println(anyMap.size());
}
Otherwise, specify the types that you need:
public void printAThroughZ(Map<Character, ?> anyCharacterMap) {
for (int i = 'A'; i <= 'Z'; i++)
System.out.println(anyCharacterMap.get((char) i));
}
In the above method, we'd need to know that the Map's key is a Character
, otherwise, we wouldn't know what type to use to get values from it. All objects have a toString()
method, however, so the map can have any type of object for its values. We can still print the values.
'development' 카테고리의 다른 글
Bazel과 Gradle의 차이점은 무엇입니까? (0) | 2020.07.04 |
---|---|
Java 웹 애플리케이션에서 애플리케이션 서버 외부에서 정적 데이터를 제공하는 가장 간단한 방법 (0) | 2020.07.04 |
position : fixed가 iPad 및 iPhone에서 작동하지 않습니다 (0) | 2020.07.04 |
Meyers의 Singleton 패턴 스레드 구현은 안전합니까? (0) | 2020.07.04 |
rbindlist가 rbind보다“더 나은”이유는 무엇입니까? (0) | 2020.07.04 |