• 13-Object&包装类


    1. Object 类的使用

    Object 类是所有 Java 类的根父类;如果在类的声明中未使用 extends 关键字指明其父类,则默认父类为 java.lang.Object 类。

    1. 仅提供空参构造器

    2. 成员方法

    1.1 finalize()

    当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。

    public class FinalizeTest {
        public static void main(String[] args) {
            Person p = new Person("Peter", 12);
            System.out.println(p);
            p = null;//此时对象实体就是垃圾对象,等待被回收。但时间不确定。
            System.gc();//强制性释放空间; 在此之前, 控制台打印 "对象被释放→..."
        }
    }
    
    class Person{
        ...
        
        //子类重写此方法,可在释放对象前进行某些操作
        @Override
        protected void finalize() throws Throwable {
            System.out.println("对象被释放→" + this);
        }
    	
        ...
    

    垃圾回收机制关键点:

    • 垃圾回收机制只回收 JVM 堆内存里的对象空间
    • 对其他物理连接,比如数据库连接、输入流输出流、Socket 连接无能为力
    • 现在的 JVM 有多种垃圾回收实现算法,表现各异。
    • 垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行
    • 可以将对象的引用变量设置为 null,暗示垃圾回收机制可以回收该对象
    • 程序员可以通过 System.gc() 或者 Runtime.getRuntime().gc() 来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定
    • 垃圾回收机制回收任何对象之前,总会先通知该对象让它调用 finalize 方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)
    • 永远不要主动调用某个对象的 finalize 方法,应该交给垃圾回收机制调用

    1.2 equals

    1.2.1 ==

    // 基本类型:比较两个变量保存的数值是否一致
    int i = 10;
    int j = 10;
    double d = 10;
    System.out.println(i == j); // true
    System.out.println(i == d); // (自动类型提升) true
    boolean b = true;
    // System.out.println(i == b); Error!
    System.out.println(b == false); // false
    char c1 = 10;
    System.out.println(i == c1); // true
    char c2 = 'A';
    char c3 = 65;
    System.out.println(c2 == c3); // true
    
    // 引用类型:比较这两个引用是否指向同一个对象实体
    Sth s1 = new Sth();
    Sth s2 = new Sth();
    System.out.println(s1 == s2); // false
    
    // 特别地, 字符串常量池
    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1 == str2); // true
    

    1.2.2 equals

    • equals:指示其他某个对象是否与此对象“相等”
    • Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)
      public boolean equals(Object obj) {
          return (this == obj);
      }
      
    • 通常会重写该方法,使之比较的是两个对象的"实体内容";但要注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码
      class Sth {
          private String attr;
          private int num;
      	
          @Override
          public int hashCode() {
              final int prime = 31;
              int result = 1;
              result = prime * result + ((attr == null) ? 0 : attr.hashCode());
              result = prime * result + num;
              return result;
          }
      	
          @Override
          public boolean equals(Object obj) {
              if (this == obj)
                  return true;
              if (obj == null)
                  return false;
              if (getClass() != obj.getClass())
                  return false;
              Sth other = (Sth) obj;
              if (attr == null) {
                  if (other.attr != null)
                      return false;
              } else if (!attr.equals(other.attr))
                  return false;
              if (num != other.num)
                  return false;
              return true;
          }
      }
      

    1.2.3 ==/equals 区别

    • == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
    • 用 == 进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错;
    • equals 的话,它是属于 java.lang.Object 类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到 String 等类的 equals 方法是被重写过的,而且 String 类在日常开发中用的比较多,久而久之,形成了 equals 是比较值的错误观点
    • 具体要看自定义类里有没有重写 Object 的 equals 方法来判断
    • 通常情况下,重写 equals 方法,会比较类中的相应属性是否都相等

    1.3 toString

    返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。

    Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    

    当调用 System.out.println(obj); 实际上就会调用 obj 的 toString 方法。

    // PrintStream
    public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }
    
    // String
    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }
    

    1.4 数组作为 Object 的子类

    public class ArrayTest {
        @Test
        public void test() {
            int[] arr = {1,2,3};
            print(arr); // [I@1698c449
            System.out.println(arr.getClass()); // class [I → [: 一维, I: int
            System.out.println(arr.getClass().getSuperclass()); // class java.lang.Object
        }
    
        public void print(Object obj) {
            System.out.println(obj);
        }
    }
    

    2. JUnit 单元测试

    • 选中当前 Project,右键选择 → Build Path → Add Libraries → JUnit
    • 创建进行单元测试的 Java 类,并在单元测试类当中导入:import org.junit.Test;
    • 并声明单元测试方法,要求:① 方法权限 public;② 无返回值 ③ 没有形式参数
    • 在此单元测试方法上需要声明注解 @Test
    • 测试方法:双击方法名选中,右键选择 → Run As → JUnit Test
      • 运行成功
      • 运行失败,抛出异常

    3. 包装类的使用

    针对 8 种基本数据类型定义相应的引用类型 —— 包装类(封装类)。让它们具有类的特征,调用类中的方法,Java 才能真正的面向对象。

    3.1 拆箱/装箱

    「装箱」将基本数据类型包装成包装类的实例。

    Integer i1 = new Integer(10); // 10
    Integer i2 = new Integer("123"); // 123
    Float f1 = new Float(12.34); // 12.34
    Float f2 = new Float(1.234f); // 1.234
    Float f3 = new Float("3.14"); // 3.14
    Float f4 = new Float("3.14abc"); // NumberFormatException!
    Boolean b1 = new Boolean(true); // true
    Boolean b2 = new Boolean("true"); // true
    Boolean b3 = new Boolean("true1234"); // false, 为什么没报错?
    

    Boolean 类源码

    public Boolean(String s) {
        this(parseBoolean(s));
    }
    public static boolean parseBoolean(String s) {
        return ((s != null) && s.equalsIgnoreCase("true"));
    }
    

    「拆箱」获得包装类对象中包装的基本类型变量。

    int a = i1.intValue();
    boolean flag = b1.booleanValue();
    Object obj = new Float(11.01);
    float f  = (Float) obj;
    

    JDK1.5之后,支持自动装箱,自动拆箱 // 类型必须匹配!

    Float f1 = 1.23f;
    Float f2 = 12.345; // Type mismatch: cannot convert from double to Float
    Boolean b1 = true;
    Double d1 = 1.2;
    Double d2 = 12; // Type mismatch: cannot convert from int to Double
    f = (float) obj; // 强制类型转换 + 自动拆箱
    float f3 = d1; // Type mismatch: cannot convert from Double to float
    double d3 = f2;
    

    3.2 与 String 转换

    1. String → 基本数据类型、包装类:[包装类] public static [WrapperClass] parseXxx("....")
    2. 基本数据类型、包装类 → String:[String] public static String valueOf(...)

    3.3 测试题

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

    Object o1 = true ? new Integer(1) : new Double(2.0);
    System.out.println(o1); // 1.0
    // ---------------------------------------------------
    Object o2;
    if (true)
        o2 = new Integer(1);
    else
        o2 = new Double(2.0);
    System.out.println(o2); // 1
    

    2. 打印结构各是什么?

    Integer i = new Integer(1);
    Integer j = new Integer(1);
    System.out.println(i == j); // false
    Integer m = 1; // 直接从IntegerCache中拿的
    Integer n = 1; // 拿的同一个
    System.out.println(m == n); // true
    Integer x = 128; // 创建新对象
    Integer y = 128; // 创建新对象
    System.out.println(x == y); // false
    

  • 相关阅读:
    vue登录注册及token验证
    react实现登录注册
    React Native仿京东客户端实现(首页 分类 发现 购物车 我的)五个Tab导航页面
    进度条效果
    手风琴切换效果
    React实现了一个鼠标移入的菜单栏效果
    react购物车
    react实现tab切换效果
    网络缓存
    java线程面试手写题
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/13113471.html
Copyright © 2020-2023  润新知