1.instanceof运算符 格式: A instanceof B
A通常是一个引用类型的变量,B通常是一个类(也可以是接口,接口是一种特殊的类),此语句用来判断A是否是B的类或者B的子类或实现类的实例。如果是,返回turue,否则返回false
代码编译时,A的编译类型必须满足以下条件:要么与B类相同,要么是B类的子类,要么是B类的父类。只有满足这三个条件之一。代码才能正常编译,否则编译失败:不可转换的类型
// 编译时为Object类型,运行时为String类型 Object A = "hello"; // 输出true System.out.println(A instanceof Object); // 输出true System.out.println(A instanceof String); // 输出false(Math是Object的子类) System.out.println(A instanceof Math); // 输出true(String实现了Comparable接口) System.out.println(A instanceof Comparable); String B = "haha"; // 编译失败 System.out.println(B instanceof Math);
此外,当引用类型的变量String C指向一个null对象时,C instanceof String 可以通过编译,但返回值为false,使用instanceof运算符的好处是:1,返回true时可以保证第一个操作数所引用的对象不是null。2,转换类型时不用担心抛出类型转换异常。
当强制类型转换,则在编译阶段强制转型要求被转型变量的编译时类型必须满足如下三个条件之一:
*被转型变量的编译时类型与目标类型相同。
*被转型变量的编译时类型是目标类型父类。
*被转型变量的编译时类型是目标类型子类。
而在运行阶段,被转型变量所引用对象的实际类型必须是目标类型的实例,或者是目标类型的子类,实现类的实例,否则在运行时会报类型转换异常。
// 编译类型为Object,实际类型为String Object A = "hello"; // 在此处编译成功,但运行失败,报类型转换异常 Math math = (Math)A; // 在此处编译失败 System.out.println(math instanceof String);
2.构造器是否创建对象
构造器只负责执行初始化对象,而在构造器执行之前,java对象所需的内存空间是由new关键字申请出来的。
使用反序列化的方式恢复java对象,如:
// 创建一个Person实例,name初始化为holley(Person重写了equals方法,同一类型,name相等才返回true) Person p = new Person("holley"); Person p2 = null; ObjectOutputStream oos = null; ObjectInputStream ois = null; try{ // 创建输出流对象 oos = new ObjectOutputStream(new FileOutputStream("a.bin")); // 创建输入流对象 ois = new ObjectInputStream(new FileInputStream("a.bin")); // 序列化输出java对象 oos.writeObject(p); oos.flush(); // 反序列化恢复java对象 p2 = (Person)ois.readObject(); // 两个对象的实例变量值完全相等,输出true System.out.println(p.equals(p2)); // 两个对象不同,输出false System.out.println(p == p2); }catch(Execption e){ e.printStackTrace(); }finally{ if(oos != null){ oos.close(); } if(ois != null){ ois.close(); } }
3.当实际调用时闯入的实参同时满足多个方法时,如果某个方法的形参要求参数范围越小,那这个方法就越精确,那么就调用此方法。如:
public class Demo{ public void info(Object o,int a){ System.out.println("o参数为:" + o); } public void info(Object[] os,int a){ System.out.println("os参数为:" + os); } } // 此时输出的是:os参数为:null.因为Object[]是Object的子类,范围更小
new Demo().info(null,3);
极端情况
public class Demo{ public void info(Object o,int a){ System.out.println("o参数为:" + o + ",a参数为:" + a); } public void info(Object[] os,double a){ System.out.println("os参数为:" + os + ",a参数为:" + a); } }
// 此时编译出错,jvm无法判断哪个方法更匹配
new Demo().info(null,3);