Java: 인스턴스(Instanceof) 및 제네릭
값의 인덱스에 대한 일반적인 데이터 구조를 살펴보기 전에 해당 유형의 인스턴스(instance)인지 확인하십시오.this
에 대한 파라메트릭을 받았어
하지만 이클립스는 내가 이렇게 하면 불평을 한다.
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
오류 메시지:
형식 매개 변수 E에 대해 검사 인스턴스(instance)를 수행할 수 없음.런타임에 일반 유형 정보가 지워지므로 삭제 개체 대신 사용
그것을 하는 더 좋은 방법은 무엇인가?
에러메세지에 다 나와 있어.런타임에 타입이 없어져서 확인할 방법이 없다.
이렇게 목적지에 맞는 공장을 만들면 잡을 수 있을 것이다.
public static <T> MyObject<T> createMyObject(Class<T> type) {
return new MyObject<T>(type);
}
그런 다음 개체 생성자 저장소에서 해당 유형을 가변적으로 저장하여 다음과 같은 방법으로 표시할 수 있도록 하십시오.
if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass()))
{
return -1;
}
제네릭을 사용하여 런타임 유형 검사를 위한 두 가지 옵션:
옵션 1 - 생성자 손상
IndexOf(...)를 재정의하는 경우 전체 컬렉션을 반복하는 동안 성능을 위해 유형을 확인하려고 함을 가정해 보십시오.
이렇게 더러운 시공자를 만들어라.
public MyCollection<T>(Class<T> t) {
this.t = t;
}
그런 다음 isAssignableFrom을 사용하여 유형을 확인하십시오.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
목표를 인스턴스화할 때마다 다음과 같이 반복해야 한다.
new MyCollection<Apples>(Apples.class);
넌 그럴 가치가 없다고 결정할지도 몰라.ArrayList.indexOf(...)의 구현에서는 유형이 일치하는지 확인하지 않는다.
옵션 2 - 실패 허용
만약 당신이 당신의 알 수 없는 타입을 필요로 하는 추상적인 방법을 사용해야 한다면, 당신이 정말로 원하는 것은 컴파일러가 인스턴스 에 대해 우는 것을 멈추는 것이다.이와 같은 방법을 사용할 경우:
protected abstract void abstractMethod(T element);
다음과 같이 사용할 수 있다.
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
당신은 컴파일러를 속이기 위해 T(당신의 일반형)에게 그 대상을 던져주는 것이다.당신의 출연진들은 런타임에 아무 것도 하지 않지만, 당신이 당신의 추상적인 방법에 잘못된 유형의 오브젝트를 전달하려고 할 때 당신은 여전히 ClassCastException을 받게 될 것이다.
비고 1: 추상적인 방법으로 확인되지 않은 추가 깁스를 하는 경우, ClassCastExceptions가 여기에서 잡힐 것이다.좋을 수도 있고 나쁠 수도 있으니까 잘 생각해 봐.
참고 2: 인스턴스(instanceof)를 사용할 때 무료 null 수표를 받으십시오.사용할 수 없기 때문에 맨손으로 null 여부를 확인해야 할 수도 있다.
이전 게시물이지만 일반 인스턴스 확인을 수행하는 간단한 방법.
public static <T> boolean isInstanceOf(Class<T> clazz, Class<T> targetClass) {
return clazz.isInstance(targetClass);
}
클래스가 일반 매개 변수를 사용하여 클래스를 확장하는 경우, 반사를 통해 해당 클래스를 런타임에 얻은 다음 비교(즉, 비교)에 사용할 수도 있다.
class YourClass extends SomeOtherClass<String>
{
private Class<?> clazz;
public Class<?> getParameterizedClass()
{
if(clazz == null)
{
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
clazz = (Class<?>)pt.getActualTypeArguments()[0];
}
return clazz;
}
}
위의 경우, 런타임에 getParameterizedClass()에서 String.class를 얻을 수 있으며, 여러 검사에서 반사 오버헤드를 받지 않도록 캐시된다.ParameterizedType.getActualTypeArguments() 방법에서 인덱스별로 다른 매개 변수화된 유형을 가져올 수 있다는 점에 유의하십시오.
나는 같은 문제를 가지고 있었고, 여기에 나의 해결책이 있다(매우 겸손, @gee: 이번에는 컴파일 AND working...).
내 프로템은 옵저버를 구현하는 추상 수업 안에 있었다.관측 가능한 화재 방법은 어떤 종류의 물체가 될 수 있는 객체 클래스로 업데이트된다(...).
T 유형의 개체만 처리하려는 경우
해결책은 런타임에 유형을 비교할 수 있도록 클래스를 생성자에게 전달하는 것이다.
public abstract class AbstractOne<T> implements Observer {
private Class<T> tClass;
public AbstractOne(Class<T> clazz) {
tClass = clazz;
}
@Override
public void update(Observable o, Object arg) {
if (tClass.isInstance(arg)) {
// Here I am, arg has the type T
foo((T) arg);
}
}
public abstract foo(T t);
}
구현을 위해 우리는 시공자에게 클래스를 전달하기만 하면 된다.
public class OneImpl extends AbstractOne<Rule> {
public OneImpl() {
super(Rule.class);
}
@Override
public void foo(Rule t){
}
}
아니면 E에 캐스팅하려는 실패한 시도를 잡을 수도 있다.
public int indexOf(Object arg0){
try{
E test=(E)arg0;
return doStuff(test);
}catch(ClassCastException e){
return -1;
}
}
기술적으로는 그럴 필요가 없다. 그것이 제네릭의 포인트인 만큼 컴파일 형식 확인을 할 수 있다.
public int indexOf(E arg0) {
...
}
그러나 @Override는 클래스 계층이 있으면 문제가 될 수 있다.그렇지 않으면 이샤이의 대답을 본다.
객체의 런타임 유형은 필터링할 수 있는 비교적 임의적인 조건이다.나는 너의 수집품에 그런 더러운 것을 가까이 하지 말 것을 제안한다.이는 단순히 필터의 수집 담당자가 구조물을 통과함으로써 달성된다.
public interface FilterObject {
boolean isAllowed(Object obj);
}
public class FilterOptimizedList<E> implements List<E> {
private final FilterObject filter;
...
public FilterOptimizedList(FilterObject filter) {
if (filter == null) {
throw NullPointerException();
}
this.filter = filter;
}
...
public int indexOf(Object obj) {
if (!filter.isAllows(obj)) {
return -1;
}
...
}
...
}
final List<String> longStrs = new FilterOptimizedList<String>(
new FilterObject() { public boolean isAllowed(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
String str = (String)str;
return str.length() > = 4;
} else {
return false;
}
}}
);
Java가 결정하도록 하고 예외적인 최종 결론을 얻도록 한다.
public class Behaviour<T> {
public void behave(Object object) {
T typedObject = null;
try { typedObject = (T) object; }
catch (ClassCastException ignored) {}
if (null != typedObject) {
// Do something type-safe with typedObject
}
}
}
참조URL: https://stackoverflow.com/questions/1570073/java-instanceof-and-generics
'IT이야기' 카테고리의 다른 글
문자열에서 문자 발생 횟수를 계산하는 방법 (0) | 2022.05.08 |
---|---|
vuejs - 동적 입력 'synamic' (0) | 2022.05.08 |
C를 사용하여 키보드에서 문자열을 읽는 방법? (0) | 2022.05.08 |
math.h를 포함함에도 불구하고 C에서 pow()에 대한 정의되지 않은 참조 (0) | 2022.05.08 |
Vuejs2: 감시자를 어떻게 파괴할 수 있을까? (0) | 2022.05.08 |