Object与Objects

一、Object类

常用方法

1.toString()

将对象转化为字符串,字符串组成为包名+类名+@+16进制的地址值

下面是底层源码:

    public String toString() {
                //包名+类名          @符号   通过一系列运算最后得到16进制的地址值 
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

我们很多时候在输出对象的时候,不用调用toString方法也会输出该结果为什么呢?这个我们就要来探讨探讨输出语句了,具体用到的类、属性、方法源码如下所示:

public final class System {
    ...
    //out为System中的静态属性,返回值为PrintStream输出流
    public final static PrintStream out = null;
    ...
}
    //用到的println方法
    public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }
    //用到的valueof方法
     public static String valueOf(Object obj) {
         //此处使用三目运算符,如果对象不为空则调用toString()方法进行输出
        return (obj == null) ? "null" : obj.toString();
    }
    public void print(String s) {
        if (s == null) {
            s = "null";
        }
        write(s);
    }
    //用到的write方法,将要输出的打印到控制台
    private void write(String s) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(s);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush && (s.indexOf('\n') >= 0))
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
    //用到的换行方法,主要就是换行
    private void newLine() {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.newLine();
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }

总结一下:toString()方法调用是在println()方法中的第一步,使用String.valueOf(x)通过三目运算符,使对象调用toString()方法转化为字符串。

2.equals(Object obj)

比较两个对象是否相同,如果没有重写则调用父类Object中的方法,具体比较的是两个对象地址值,具体源码如下:

    public boolean equals(Object obj) {
    //this是调用该方法的对象,与传进来的对象进行==判断
    //进行地址值的判断
        return (this == obj);
    }

如果想要比较对象中属性则需要重写equals(Object obj)方法,代码如下:

    @Override
    public boolean equals(Object o) {
        //1.先比较两个对象地址
        if (this == o) return true;
        //2.对传入的对象进行非空,以及类型进行判断
        if (o == null || getClass() != o.getClass()) return false;
        //3.然后将传入的对象强转为当前对象类型
        User user = (User) o;
        //4.然后对里面的各个属性进行判断
        return Objects.equals(id, user.id) && Objects.equals(username, user.username);
    }

重写后的equals()方法可以总结为下面四步:

1.先比较两个对象地址

2.对传入的对象进行非空,类型进行判断

3.然后将传入的对象强转为当前对象类型

4.对里面涉及的属性进行判断

这里有一个题目,大家可以试着写一下(提示一下:这里涉及toString()方法重写)

        String s = new String("123");
        StringBuffer stringBuffer = new StringBuffer("123");
        
        //思考一下这两个输出语句的值
        System.out.println(s.equals(stringBuffer));
        System.out.println(stringBuffer.equals(s));

3.clone(int a)对象克隆

这个方法有一个特殊的一点,该方法是由protected修饰的,只能在本包中(package java.lang),调用,所有在重写该方法时,应要用父类调用该方法。具体代码如下:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Cloneable{
    private Integer id;//游戏角色
    private String username;//用户名
    private String password;//密码
    private String path;//游戏图片
    private int[] data;//游戏进度

    @Override
    public String toString() {
        return "游戏角色:"+id+",用户名:"+username+",密码:"+password+",游戏图片:"+path+",游戏进度:"+arrToString();
    }
    private String arrToString(){
        StringJoiner sj = new StringJoiner(",","[","]");
        for (int i = 0; i < data.length; i++) {
            sj.add(data[i]+"");
        }
        return sj.toString();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //让父类帮我们调用clone方法,并将结果返回
        return super.clone();
    }
}

总结来说一共三步:

1.重写Object中的clone()方法

2.实现Cloneable接口,这个接口里面没有抽象方法,就是个标志,标志着可以进行对象克隆

3.创建对象调用clone()方法

然后就是在main方法中进行测试,具体代码如下所示:

public static void main(String[] args) throws CloneNotSupportedException, JsonProcessingException {
        int[] data = {1,2,3,4,5,6,7,8,9,0};

        //1.浅克隆
        User user = new User(5,"lsh","929126","a.img",data);
        //底层会帮我们创建一个新的对象,并将原来的数据拷贝过去
        User user2 = (User) user.clone();

        //验证Objec中克隆为浅克隆
        int[] data1 = user.getData();
        data1[0] = 100;

        System.out.println(user);
        System.out.println(user2);

    }

只是重写父类中的方法,不做处理,这个只是克隆中的浅克隆。由此引出克隆的几种形式,分别是浅克隆与深克隆,下面分别以图的形式介绍两者,以及两者之间的区别。

1.浅克隆

2.深克隆

3.两者的区别

简单来说两者区别:

1.浅克隆:两个对象中的引用数据类型(String除外)共用同一个,其中一个改变,两个都改变。

2.深克隆:两个对象中的引用数据类型(String除外)不是同一个,两者独立操作互不影响。

接下来,对我们刚刚写的浅克隆进行修改,只需在重写的方法里面进行一些处理即可,具体代码如下所示:

@Override
    protected Object clone() throws CloneNotSupportedException {
        //1.创建新的数组
        int[] newData = new int[data.length];
        //2.赋值新数组的值
        for (int i = 0; i < data.length; i++) {
            newData[i] = data[i];
        }

        //3.调用父类中的clone()方法,获取浅克隆对象
        User u = (User) super.clone();
        //4.将该对象中的数组替换为新的数组
        u.data = newData;
        return u;
    }

实现深克隆还可以引用第三方jar包Gson、ObjectMapper(Maven工程的话导入依赖即可,普通的需要在网上下载相应的jar包)具体代码如下:

        int[] data = {1,2,3,4,5,6,7,8,9,0};
        User user = new User(5,"lsh","929126","a.img",data);        
        //第三方jar包gson
        Gson gson = new Gson();
        String json = gson.toJson(user);
        System.out.println("gson序列化"+json);
        User user2 = gson.fromJson(json, User.class);

        int[] data1 = user.getData();
        data1[0] = 100;
        System.out.println(user);
        System.out.println(user2);

        //ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper();
        String s = objectMapper.writeValueAsString(user);
        System.out.println(s);
        User user3 = objectMapper.readValue(s, User.class);

        int[] data1 = user.getData();
        data1[0] = 100;
        System.out.println(user);
        System.out.println(user3);

具体操作步骤可以分为两步:

1.将user对象转化为JSON格式的字符串

2.将JSON格式的字符串转化为User类型的对象

二、Objects

常用方法

public static boolean equals(Object a, Object b) 先做非空判断比较两个对象
public static boolean isNull(Object obj) 判断对象是否为null,为null则为true,反之false
public static boolean nonNull(Object obj) 判断对象是否为null和isNull()方法相反

具体代码如下:

public static void main(String[] args) {
        /*
        public static boolean equals(Object a, Object b)   先做非空判断比较两个对象
        public static boolean isNull(Object obj)           判断对象是否为null,为null则为true,反之
        public static boolean nonNull(Object obj)          判断对象是否为null和isNull()方法相反
        */

        Student student1 = null;
        Student student2 = new Student("ls",20);

        boolean equals = Objects.equals(student1, student2);
        System.out.println(equals);
        System.out.println("---------------------------------------");
        System.out.println("student1:"+Objects.isNull(student1));//true
        System.out.println("student2:"+Objects.isNull(student2));//false
        System.out.println("----------------------------------------");
        System.out.println("student1:"+Objects.nonNull(student1));//false
        System.out.println("student2:"+Objects.nonNull(student2));//true
    }

Objects这个就是就是个工具类,最常用的方法还是equals(),替我们做了非空判断,省略了一些代码。

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ObjectObjects是Java中的两个不同的概念。 1. ObjectJava中所有类的基类。它是一个通用的引用类型,可以用来表示任何其他类的对象。所有的类都直接或间接地继承自Object类。Object类中定义了一些通用的方法,如equals()、hashCode()、toString()等,这些方法可以在所有的类中使用。 2. Objects是Java中的一个工具类,它提供了一些静态方法来操作对象。Objects类中的方法主要用于处理对象的比较、哈希码生成和空值处理等。其中,equals()方法用于比较两个对象是否相等,hashCode()方法用于生成对象的哈希码,toString()方法用于将对象转换为字符串表示。Objects类还提供了一些其他的方法,如requireNonNull()用于检查对象是否为空,isNull()和nonNull()用于判断对象是否为空等。 下面是一个示例代码,演示了如何使用ObjectObjects类: ```java import java.util.Objects; public class Person { private String name; public Person(String name) { this.name = name; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Person)) { return false; } Person other = (Person) obj; return Objects.equals(this.name, other.name); } @Override public int hashCode() { return Objects.hash(name); } @Override public String toString() { return "Person [name=" + name + "]"; } } public class Main { public static void main(String[] args) { Person p1 = new Person("Alice"); Person p2 = new Person("Bob"); System.out.println(p1.equals(p2)); // 输出:false System.out.println(Objects.equals(p1, p2)); // 输出:false System.out.println(Objects.hashCode(p1)); // 输出:961 System.out.println(Objects.toString(p1)); // 输出:Person [name=Alice] } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值