instanceof 和isInstance

本文详细介绍了Java中的instanceof关键字用于判断对象是否为指定类或其子类,以及isInstance()方法的使用场景,包括对象类型检查、多态和基本类型转换。

一、instanceof 关键字

instanceof :

java的一个二元运算符,也是一个关键字
判断左边对象是否是右边类本身或者子类

A instanceof B:

A为对象实例(A只能为引用数据类型),B为类名
@Data
@SuperBuilder
@AllArgsConstructor
public class Test<T> {

}

public interface TestInterface {
}

@Data
@SuperBuilder
@AllArgsConstructor
public class MyTest extends Test<Character> implements TestInterface{

    public static void main(String[] args) {
        MyTest myTest = MyTest.builder().build();
        System.out.println(myTest instanceof MyTest);//true
        System.out.println(myTest instanceof Test);//true
        System.out.println(myTest instanceof TestInterface);//true
        
        System.out.println("hello world" instanceof String);//true
        System.out.println("hello world" instanceof Object);//true
        
		List<String> list = new ArrayList<>();
        System.out.println(list instanceof ArrayList);//true
        System.out.println(list instanceof Object);//true

        System.out.println(null instanceof Object);//false
        System.out.println(null instanceof String);//false
        System.out.println(null instanceof MyTest);//false

    }
}

注意左边只能为引用数据类型,否则会报错:
在这里插入图片描述

向上转型(多态):

子类对象可以向上转为父类对象,接口实现类对象可以向上转为接口对象。

null instanceof 都为false:

因为引用类型的默认值都为null,所以null可以转换成为任何类型,不属于任何类型

二、isInstance()方法

MyTest.class.isInstance(myTest)
判断对象是否是参数对象本身或者父类(推荐把父类写在前面,即父类调用方法) 参数可以是基本类型,自动做了装箱操做

注意自动拆装箱是在JDK1.5以后引入的

MyTest myTest = MyTest.builder().build();

//不推荐通过子类调用isInstance(),可能需要强转
System.out.println(MyTest.class.isInstance(myTest));//true
System.out.println(MyTest.class.isInstance(Test.builder().build()));//false
System.out.println(MyTest.class.isInstance((TestInterface)myTest));//true

System.out.println(MyTest.class.isInstance(new Object()));//false

//推荐把父类写在前面,即父类调用方法
System.out.println(TestInterface.class.isInstance(myTest));//true
System.out.println(Test.class.isInstance(myTest));//true
System.out.println(Object.class.isInstance(myTest));//true
System.out.println(Object.class.isInstance(new Object()));//true

System.out.println(Test.class.isInstance(new Object()));//false

List<Object> arrayList = new ArrayList<>();

System.out.println(List.class.isInstance(arrayList));//true
System.out.println(List.class.isInstance(new Object()));//false
System.out.println(List.class.isInstance(new LinkedList<>()));//true

//参数可以是基本类型 自动做了装箱操做
System.out.println(Integer.class.isInstance(1));//true
System.out.println(Integer.class.isInstance(1.1));//false

System.out.println(Double.class.isInstance(1.6));//true
System.out.println(Double.class.isInstance(1));//false
Java中,泛型`instanceof`的搭配使用存在一定的限制,这是因为Java泛型在运行时是通过类型擦除(Type Erasure)实现的,即泛型信息在编译后会被擦除,仅保留原始类型(通常是`Object`)。因此,直接使用`instanceof`来判断泛型类型是不可行的。 ### `instanceof`的使用方法 `instanceof`用于检查一个对象是否是某个类的实例,或者是否实现了某个接口。它的基本用法如下: ```java if (obj instanceof SomeClass) { // obj 是 SomeClass 或其子类的实例 } ``` 需要注意的是,`instanceof`不能用于基本数据类型,只能用于对象类型。此外,它判断的是对象的“本质”类型,即实际创建时的类,而不是变量的声明类型[^1]。 ### 泛型与`instanceof`的限制 由于泛型在运行时被擦除,以下代码是非法的: ```java if (obj instanceof T) { // 编译错误 // ... } ``` 这是因为`T`在运行时并不存在,它只是编译时的类型检查工具。因此,不能直接使用`instanceof`来判断泛型参数的具体类型。[^4] ### 替代方案 #### 1. 使用`Class<T>`对象进行类型检查 可以通过传递一个`Class<T>`对象来在运行时保留类型信息。例如: ```java public class MyCollection<T> { private final Class<T> type; public MyCollection(Class<T> type) { this.type = type; } public boolean isInstance(Object obj) { return type.isInstance(obj); } } ``` 这样在创建实例时传入具体的类型信息: ```java MyCollection<String> collection = new MyCollection<>(String.class); boolean result = collection.isInstance("hello"); // true ``` 这种方式允许在运行时进行类型检查,但需要额外传递类型信息[^2]。 #### 2. 使用强制类型转换并捕获异常 另一种方式是尝试将对象强制转换为泛型类型,并在失败时捕获`ClassCastException`: ```java public int indexOf(Object o) { try { T element = (T) o; // 使用 element 进行操作 } catch (ClassCastException | NullPointerException e) { // 处理类型不匹配或 null 值 } } ``` 这种方法适用于你希望让编译器停止对`instanceof`的检查,并且愿意承担运行时异常的风险[^2]。 #### 3. 泛型方法中的类型检查 在泛型方法中,可以结合`Class<T>`反射机制来实现更灵活的类型检查: ```java public static <T> boolean isOfType(Object obj, Class<T> type) { return type.isInstance(obj); } ``` 使用示例: ```java boolean isString = isOfType("hello", String.class); // true ``` 这种方式可以避免直接使用`instanceof`带来的限制,同时保持代码的类型安全性[^2]。 --- ### 总结 Java的泛型设计初衷是为了在编译时提供更强的类型安全性,而不是为了实现运行时的类型检查。因此,直接使用`instanceof`来判断泛型类型是不可行的。可以通过传递`Class<T>`对象、使用反射机制或捕获类型转换异常等方式来实现运行时的类型检查。这些方法虽然不如直接使用`instanceof`直观,但在某些场景下是可行的替代方案[^3]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值