Java面向对象(中)--super/多态/向下转型/equals/toString/包装类/单元测试工具
java对象
方法重写
子类继承父类以后,可以对父类同名同参数的方法,进行覆盖操作
重写后,当创建子类对象以后,通过子类对象调用子父类中同名同参数的方法时,执行的是子类重写父类的方法。
如何区分方法重写和重载:
① 重载是同一个类中声明方法名相同但参数不同的方法,构造器可以重载,重写是子类继承父类以后,可以对父类同名同参数的方法,进行覆盖操作。
② 重载和重写的具体规则
③ 重载不表现为多态性,重写表现为多态性
super调用
可以用来调用的结构:属性、方法、构造器
super调用属性、方法:
通常情况下,子类的方法或构造器中可以使用super显示调用父类中声明的属性或方法,但是通常情况下会省略;当子类和父类定义了同名属性或重载了方法时时,在子类中调用父类的属性或方法必须显式的使用super.属性或super.方法的方式;
super调用构造器:
- super(形参列表)的使用,必须声明在子类构造器的首行。
- 在类的构造器中,针对this(形参列表)或super(形参列表)只能二一,不能同时出现
- 在构造器的首行,没显式的声明this(形参列表)或super(形参列表),则默认调用构造器super()
- 在类的多个构造器中,至少一个类的构造器中使用了super(形参列表),调用父类的构造器
多态性
对象的多态性:父类的引用指向子类的对象
多态的使用:虚拟方法调用:有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类复写父类的方法。
如 Father abc=new Son()
那么abc.getName()调用的是子类son中的方法(前提是该方法被重写了)
-
多态性只用于方法,属性不适用(运行和编译都看左边)
-
多态性是运行时行为
-
多态性的使用前提①类的继承关系②方法的重写
向下转型
有了对象的多态性后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时只能调用父类声明的属性和方法,子类特有的属性和方法不能调用。
- 如何才能调用子类特有的方法和属性?
向下转型,使用强制类型转换符
Person p2=new Man();//Person是Man的父类
Man m1=(Man)p2;//此时m1可以使用子类的方法和属性
- 要注意什么问题
可能出现ClassCastException异常。应该使用instanceof在进行向下转型前判断
instanceof关键字
if(a instanceof A)
判断对象a是否是类A的实例
可用于防止强转时出现ClassCastException的异常,向下转型前通常先进行instanceof的判断
if(p2 instanceof Woman){
Woman w1=(Woman)p2;
w1.goShopping();
}
Object类
java.lang.Object类
- Object类是所有java类的根父类
- 如果类的声明中未使用extends指明其父类,则默认父类为java.lang.Object类
- Object类中的功能具有通用性
- Object类只声明了一个空参的构造器
常用方法
- clone() 用于克隆对象
- equals()比较两个对象是否相等
- 内存回收:
Sysyem.gc
通知JVM回收垃圾对象,回收前会调用finalize方法
equals()
面试题:==和equals()区别
1.==运算符
- 可以使用在基本数据类型变量和引用数据类型变量中
- 如果比较的是基本数据类型变量,则比较两个变量保存的数据是否相等;如果比较的是引用数据类型变量,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
2.equals()方法的使用
- Object类中equals()的定义
public boolean equals(Object obj){
return (this==obj);
}
- 只能用于引用数据类型,比较两个对象的地址值是否相同
- String、Date、File、包装类等都重写了Obejct类中的equals()方法,重写后,比较的不是两个引用的地址值是否相同,而是两个对象的实体内容是否相同。
equals类重写:比较两个类实体内容
有时需要重写,用于比较两个对象的实体内容是否相同
public boolean equals(Object obj){//重写了Customer类
if(this==obj){
return true;
}
if(obj instanceof Customer){
Customer cust=(Customer)obj;
return this.age==cust.age &&this.name.equals(cust.name)
}
else
return false;
}
toString
-
当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
-
Object类中toSting()的定义:
public String toString(){
return getClass().getName()+@+Integer.toHexString(hashCode());
}
- String、Date、File、包装类等都重写了Obejct类中的toString方法,重写后,返回的是实体内容信息
- 自定义类也可以重写toString方法,返回实体内容信息
public String roString(){
return "Customer[name="+name+",age="+age+"]";
}
包装类的使用
针对八种基本数据类型定义相应的引用类型——包装类(封装类);有了类的特点,就可以调用类中的方法,这就是Java的面向对象
基本数据类型转换为包装类
有些方法形参是类类型,某些基本数据类型必须转化为包装类才能使用
int num=10;
Integer in1=new Integer(num);
System.out.println(in1.toString());
包装类转化为基本数据类型
包装类无法加减乘除,有时候需要转化为基本数据类型
Integer in1=new Integer(12);
int i1=in1.intValue();//转化为基本数据类型
System.out.println(i1+1);
floatValue()使用方法类似
自动装箱与自动拆箱
JDK 5.0时加入
//自动装箱 基本数据类型---包装类
int num1=10;
Integer in1=num1;//不需要再调用包装类构造器,可以直接等于
//自动拆箱 包装类---基本数据类型
int num2=in1;
基本数据类型包装类转化为string
int num1=10;
String str1=num+"";//方式一:连接运算
float f1=12.3f;
String str2=string.valueOf(f1);//方法二:调用String的valueOf
string转化为基本数据类型包装类(重要)
//调用包装类的parseXXX方法
String str1="123";
Integer in1=Integer.parseInt(str1);
String str2="true";
boolean b1=Boolean.parseBoolean(str2);
单元测试工具使用
- 选中当前工程,右键选择:build path-add libraries-JUnit4-下一步
- 创建Java类,进行单元测试
要求:①此类是public的②此类提供公共的无参的构造器
- 此类中声明单元测试方法:方法的权限是public,没有返回值类型,没有形参,尽量用testxxx命名
- 此单元测试方法上需要声明 @Test,并在单元测试类中导入:import org.junit.Test;
- 写完代码以后,左键双击单元测试方法名,右键run as-JUnit Test
- 如果执行结果没有任何异常,绿条,出现异常时为红条
面试题
多态性理解
- 实现代码之间的通用性
- 如object类中定义的equals方法,输入参数为Object obj,此时object所有子类对象都可以作为参数调用这个方法;使用java程序操作(获取数据库连接、CRUD)数据库(MySQL)
- 抽象类、接口的使用肯定体现了多态性(抽象类、接口不能实例化)
包装类使用
如下两个题目输出结果相同吗?各是什么?
Object o1=true?new Integer(1):new Double(2.0);
System.out.println(o1);
Object o2;
if(true)
o2=new Integer(1);
else
o2=new Double(2.0);
System.out.println(o2);
第一个输出1.0第二个输出1
- 为什么Object o1=true?
-
因为Object类是所有Java类的祖先,每个类都使用 Object 作为超类。
-
所有对象(包括数组)都实现这个类的方法,可以使用类型为Object的变量指向任意类型的对象。
true是布尔数据类型,可标记为boolean o=true。基于以上两点,Object o1=o成立,进而Object o1=true正确。
-
三元运算符存在自动类型提升,判定为Integer(1)后会提升为double类型;第二种代码则不会
-
包装类重写了toString输出的不是地址而是实体内容
==的使用
Integer i=new Integer(1);
Integer j=new Integer(1);
System.out.println(i==j);//false 比较两个对象时==比较的是地址
Integer m=1;//自动装箱
Integer n=1;
System.out.println(m==n);//true
//Integer内部定义了IntegerCache结构,其中定义了Integer[],保存了从-128~127范围的正数,如果我们使用自动装箱的方式,给Integer赋值的范围在-128~127范围内,可以直接使用数组中的元素,不用去new了
Integer x=128;
Integer y=128;
System.out.println(i==j);//false
//[-128,127]以外的数字是在堆里new出来的,相当于new了一个Integer对象
==和equals()区别
1.==运算符
- 可以使用在基本数据类型变量和引用数据类型变量中
- 如果比较的是基本数据类型变量,则比较两个变量保存的数据是否相等;如果比较的是引用数据类型变量,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
2.equals()方法的使用
- Object类中equals()的定义
public boolean equals(Object obj){
return (this==obj);
}
- 只能用于引用数据类型,比较两个对象的地址值是否相同
- String、Date、File、包装类等都重写了Obejct类中的equals()方法,重写后,比较的不是两个引用的地址值是否相同,而是两个对象的实体内容是否相同。