面向对象(中)学习笔记三
一、instanceof关键字
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明的是父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法呢?向下转型:使用强制转换符。使用强转时可能出现ClassCastException的异常
instanceof关键字的使用:
a instanceof A:判断关键字a是否是类A的实例。如果是,返回true;如果不是,返回false。
如果x属于类A的子类B,x instanceof A值也为true。
- instanceof的使用情景
为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
如果a instanceof A返回true。并且a instanceof B也返回true。则类B是类A的父类。
向下转型的几个问题
多态练习:
- 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统不可能把父类里的方法转移到子类中。
- 对于实例变量则不存在这样的现象,即使子类定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量,编译运行都看左边。
二、Object类的使用
java.lang.Object
Object类是所有Java类的根父类
数组也作为Object类的子类出现,可以调用Object类中声明的方法。
如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
Object类中的功能(属性和方法)具有通用性
- clone() 克隆一个新的对象
- finalize() 垃圾回收:当一个对象在堆空间中发现没有任何引用指向这个对象了,垃圾回收期就会回收这个对象。在一个对象被回收之前会调用这个方法。
- final、finally、finalize的区别
- getClass() 获取当前对象的所属类。
- hashCode() 返回当前对象的hash值
- Object类无属性
Object只声明了一个空参构造器
面试题:== 和 equals()的区别
==:是一个运算符
1:可以使用在基本数据类型变量和引用数据类型变量中
2:如果比较的是基本数据类型的变量:比较的是两个变量保存的数据是否相等(不一定类型相等)。如果比较的引用数据类型:比较的是两个对象的地址值是否相同。即两个引用是否指向同一个对象实体。
补充:== 符号使用时,必须保证符号左右两边的变量类型一致(可自动转换的基本数据类型除外),否则编译出错。
equals():
1:是一个方法,而非运算符
2:只能适用于引用数据类型
3:Object类中的equals()的定义:
public boolean equals(Object obj) {return (this == obj);}
说明:Object类中定义的equals()和==的作用是相同的:比较的是两个对象的地址值是否相同。
4:像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容(内部的属性)”是否相同。
5:通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的“实体内容”是否相同。那么我们就需要对Object类中的equals()进行重写。看举例
重写的原则:比较两个对象的实体内容是否相同。
equals()例题

Object类中toString()的使用
当我们输出一个对象的引用时,实际上就是调用当前对象的toString()方法
Object类中toString()的定义
public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode())}
像String、Date、File、包装类等都重写了Object类中的toString()方法。使得在调用对象的toString()方法时,返回“实体内容”信息。
自定义类也可以重写toString()方法,当调用此方法时,返回对象的“实体内容”。
三、单元测试的方法
Java中的JUnit单元测试
步骤
1、选择当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步
创建Java类,进行单元测试。此时Java类型要求:1、此类是public的。2、此类提供公共的无惨的构造器。
此类中声明单元测试方法。
此时的单元测试方法:方法的权限是public,没有返回值,没有形参此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test
声明好单元测试以后,就可以在方法体内测试相关的代码。
写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
说明:如果执行结果没有任何异常,绿条。如果执行结果出现异常,红条。
四、包装类的使用

基本数据类型、包装类、String三者之间的转换
基本数据类型—->包装类:调用包装类的构造器。看举例 ```java //基本数据类型 —->包装类:1、调用包装类的构造器 2、调用包装类的valueOf()方法 3、自动装箱 @Test public void test1(){
int num1 = 10;
// System.out.println(num1.toString());
Integer in1 = new Integer(num1);System.out.println(in1.toString());//调用valueOf()方法Integer aa = Integer.valueOf(num1);Integer in2 = new Integer("123");System.out.println(in2.toString());//报异常
// Integer in3 = new Integer(“123abc”); // System.out.println(in3.toString());
Float f1 = new Float(12.3f);Float f2 = new Float("12.3");System.out.println(f1);System.out.println(f2);Boolean b1 = new Boolean(true);Boolean b2 = new Boolean("TrUe");System.out.println(b2);Boolean b3 = new Boolean("true123");System.out.println(b3);//false:忽略大小写之后只要不是true,就会认为是false
Order order = new Order();System.out.println(order.isMale);//falseSystem.out.println(order.isFemale);//null}
-包装类--->基本数据类型:调用包装类的xxxValue()```java//包装类--->基本数据类型:调用包装类Xxx的xxxValue()@Testpublic void test2(){Integer in1 = new Integer(12);int i1 = in1.intValue();System.out.println(i1 + 1);Float f1 = new Float(12.3);float f2 = f1.floatValue();System.out.println(f2 + 1);}
JDK5.0新特性:自动装箱与自动拆箱
- 装箱:将基本类型用它们对应的引用类型包装起来
- 拆箱:将包装类型转换为基本数据类型
从字节码中,我们发现装箱其实就是调用了 包装类的
valueOf()方法,拆箱其实就是调用了xxxValue()方法。
Integer i = 10等价于Integer i = Integer.valueOf(10)
int n = i等价于int n = i.intValue()
/** JDK 5.0 新特性:自动装箱 与自动拆箱*/@Testpublic void test3(){// int num1 = 10;// //基本数据类型-->包装类的对象// method(num1);//自动装箱:基本数据类型 --->包装类int num2 = 10;Integer in1 = num2;//自动装箱boolean b1 = true;Boolean b2 = b1;//自动装箱//自动拆箱:包装类--->基本数据类型System.out.println(in1.toString());int num3 = in1;//自动拆箱}public void method(Object obj){System.out.println(obj);}
基本数据类型、包装类—->String类型:调用String重载的valueof(Xxx xxx)
//基本数据类型、包装类--->String类型:调用String重载的valueOf(Xxx xxx)@Testpublic void test4(){int num1 = 10;//方式1:连接运算String str1 = num1 + "";//方式2:调用String的valueOf(Xxx xxx)float f1 = 12.3f;String str2 = String.valueOf(f1);//"12.3"Double d1 = new Double(12.4);String str3 = String.valueOf(d1);System.out.println(str2);System.out.println(str3);//"12.4"}
String类型—->基本数据类型、包装类:调用包装类的parseXxx(String s)方法
//String类型 --->基本数据类型、包装类:调用包装类的parseXxx(String s)@Testpublic void test5(){String str1 = "123";//错误的情况:// int num1 = (int)str1;// Integer in1 = (Integer)str1;//可能会报NumberFormatExceptionint num2 = Integer.parseInt(str1);System.out.println(num2 + 1);String str2 = "true1";boolean b1 = Boolean.parseBoolean(str2);System.out.println(b1);}

包装类常见面试题
package com.atguigu.java2;import org.junit.Test;/** 关于包装类使用的面试题***/public class InterviewTest {@Testpublic void test1() {Object o1 = true ? new Integer(1) : new Double(2.0);//三元运算符会统一类型,System.out.println(o1);// 1.0}@Testpublic void test2() {Object o2;if (true)o2 = new Integer(1);elseo2 = new Double(2.0);System.out.println(o2);// 1}@Testpublic void test3() {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j);//false//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率Integer m = 1;Integer n = 1;System.out.println(m == n);//trueInteger x = 128;//相当于new了一个Integer对象Integer y = 128;//相当于new了一个Integer对象System.out.println(x == y);//false}}
