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

  1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()

  2. Object类中toSting()的定义:

public String toString(){
    return getClass().getName()+@+Integer.toHexString(hashCode());
}
  1. String、Date、File、包装类等都重写了Obejct类中的toString方法,重写后,返回的是实体内容信息
  2. 自定义类也可以重写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);

单元测试工具使用

  1. 选中当前工程,右键选择:build path-add libraries-JUnit4-下一步
  2. 创建Java类,进行单元测试

要求:①此类是public的②此类提供公共的无参的构造器

  1. 此类中声明单元测试方法:方法的权限是public,没有返回值类型,没有形参,尽量用testxxx命名
  2. 此单元测试方法上需要声明 @Test,并在单元测试类中导入:import org.junit.Test;
  3. 写完代码以后,左键双击单元测试方法名,右键run as-JUnit Test
  • 如果执行结果没有任何异常,绿条,出现异常时为红条

面试题

多态性理解

  1. 实现代码之间的通用性
  2. 如object类中定义的equals方法,输入参数为Object obj,此时object所有子类对象都可以作为参数调用这个方法;使用java程序操作(获取数据库连接、CRUD)数据库(MySQL)
  3. 抽象类、接口的使用肯定体现了多态性(抽象类、接口不能实例化)

包装类使用

如下两个题目输出结果相同吗?各是什么?

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?
  1. 因为Object类是所有Java类的祖先,每个类都使用 Object 作为超类。

  2. 所有对象(包括数组)都实现这个类的方法,可以使用类型为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()方法,重写后,比较的不是两个引用的地址值是否相同,而是两个对象的实体内容是否相同。
posted @ 2021-11-21 16:38  清梨  阅读(97)  评论(0编辑  收藏  举报