面向对象(中)学习笔记三

一、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()的定义:

  1. public boolean equals(Object obj) {
  2. return (this == obj);

}

说明:Object类中定义的equals()和==的作用是相同的:比较的是两个对象的地址值是否相同。

4:像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容(内部的属性)”是否相同。

5:通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的“实体内容”是否相同。那么我们就需要对Object类中的equals()进行重写。看举例

重写的原则:比较两个对象的实体内容是否相同。

  • equals()例题
    day13_java面向对象(中)学习笔记3 - 图1

  • Object类中toString()的使用

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

    • Object类中toString()的定义

      1. public String toString() {
      2. return getClass().getName() + "@" + Integer.toHexString(hashCode())
      3. }
  • 像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

  • 说明:如果执行结果没有任何异常,绿条。如果执行结果出现异常,红条。

四、包装类的使用

day13_java面向对象(中)学习笔记3 - 图2

基本数据类型、包装类、String三者之间的转换

  • 基本数据类型—->包装类:调用包装类的构造器。看举例 ```java //基本数据类型 —->包装类:1、调用包装类的构造器 2、调用包装类的valueOf()方法 3、自动装箱 @Test public void test1(){

    1. int num1 = 10;

    // System.out.println(num1.toString());

    1. Integer in1 = new Integer(num1);
    2. System.out.println(in1.toString());
    3. //调用valueOf()方法
    4. Integer aa = Integer.valueOf(num1);
    5. Integer in2 = new Integer("123");
    6. System.out.println(in2.toString());
    7. //报异常

    // Integer in3 = new Integer(“123abc”); // System.out.println(in3.toString());

    1. Float f1 = new Float(12.3f);
    2. Float f2 = new Float("12.3");
    3. System.out.println(f1);
    4. System.out.println(f2);
    5. Boolean b1 = new Boolean(true);
    6. Boolean b2 = new Boolean("TrUe");
    7. System.out.println(b2);
    8. Boolean b3 = new Boolean("true123");
    9. System.out.println(b3);//false:忽略大小写之后只要不是true,就会认为是false
  1. Order order = new Order();
  2. System.out.println(order.isMale);//false
  3. System.out.println(order.isFemale);//null
  4. }
  1. -
  2. 包装类--->基本数据类型:调用包装类的xxxValue()
  3. ```java
  4. //包装类--->基本数据类型:调用包装类Xxx的xxxValue()
  5. @Test
  6. public void test2(){
  7. Integer in1 = new Integer(12);
  8. int i1 = in1.intValue();
  9. System.out.println(i1 + 1);
  10. Float f1 = new Float(12.3);
  11. float f2 = f1.floatValue();
  12. System.out.println(f2 + 1);
  13. }
  • JDK5.0新特性:自动装箱与自动拆箱

    • 装箱:将基本类型用它们对应的引用类型包装起来
    • 拆箱:将包装类型转换为基本数据类型

      从字节码中,我们发现装箱其实就是调用了 包装类的valueOf()方法,拆箱其实就是调用了 xxxValue()方法。

  • Integer i = 10 等价于 Integer i = Integer.valueOf(10)

  • int n = i 等价于 int n = i.intValue()

  1. /*
  2. * JDK 5.0 新特性:自动装箱 与自动拆箱
  3. */
  4. @Test
  5. public void test3(){
  6. // int num1 = 10;
  7. // //基本数据类型-->包装类的对象
  8. // method(num1);
  9. //自动装箱:基本数据类型 --->包装类
  10. int num2 = 10;
  11. Integer in1 = num2;//自动装箱
  12. boolean b1 = true;
  13. Boolean b2 = b1;//自动装箱
  14. //自动拆箱:包装类--->基本数据类型
  15. System.out.println(in1.toString());
  16. int num3 = in1;//自动拆箱
  17. }
  18. public void method(Object obj){
  19. System.out.println(obj);
  20. }
  • 基本数据类型、包装类—->String类型:调用String重载的valueof(Xxx xxx)

    1. //基本数据类型、包装类--->String类型:调用String重载的valueOf(Xxx xxx)
    2. @Test
    3. public void test4(){
    4. int num1 = 10;
    5. //方式1:连接运算
    6. String str1 = num1 + "";
    7. //方式2:调用String的valueOf(Xxx xxx)
    8. float f1 = 12.3f;
    9. String str2 = String.valueOf(f1);//"12.3"
    10. Double d1 = new Double(12.4);
    11. String str3 = String.valueOf(d1);
    12. System.out.println(str2);
    13. System.out.println(str3);//"12.4"
    14. }
  • String类型—->基本数据类型、包装类:调用包装类的parseXxx(String s)方法

    1. //String类型 --->基本数据类型、包装类:调用包装类的parseXxx(String s)
    2. @Test
    3. public void test5(){
    4. String str1 = "123";
    5. //错误的情况:
    6. // int num1 = (int)str1;
    7. // Integer in1 = (Integer)str1;
    8. //可能会报NumberFormatException
    9. int num2 = Integer.parseInt(str1);
    10. System.out.println(num2 + 1);
    11. String str2 = "true1";
    12. boolean b1 = Boolean.parseBoolean(str2);
    13. System.out.println(b1);
    14. }


day13_java面向对象(中)学习笔记3 - 图3

包装类常见面试题

  1. package com.atguigu.java2;
  2. import org.junit.Test;
  3. /*
  4. * 关于包装类使用的面试题
  5. *
  6. *
  7. */
  8. public class InterviewTest {
  9. @Test
  10. public void test1() {
  11. Object o1 = true ? new Integer(1) : new Double(2.0);//三元运算符会统一类型,
  12. System.out.println(o1);// 1.0
  13. }
  14. @Test
  15. public void test2() {
  16. Object o2;
  17. if (true)
  18. o2 = new Integer(1);
  19. else
  20. o2 = new Double(2.0);
  21. System.out.println(o2);// 1
  22. }
  23. @Test
  24. public void test3() {
  25. Integer i = new Integer(1);
  26. Integer j = new Integer(1);
  27. System.out.println(i == j);//false
  28. //Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
  29. //保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在
  30. //-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率
  31. Integer m = 1;
  32. Integer n = 1;
  33. System.out.println(m == n);//true
  34. Integer x = 128;//相当于new了一个Integer对象
  35. Integer y = 128;//相当于new了一个Integer对象
  36. System.out.println(x == y);//false
  37. }
  38. }

包装类课后练习