<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:wfw="http://wellformedweb.org/CommentAPI/">
<channel>
<title>LuckyDu - Java面试题</title>
<link>https://blog.anlucky.cn/index.php/tag/Java%E9%9D%A2%E8%AF%95%E9%A2%98/</link>
<atom:link href="https://blog.anlucky.cn/index.php/feed/tag/Java%E9%9D%A2%E8%AF%95%E9%A2%98/" rel="self" type="application/rss+xml" />
<language>zh-CN</language>
<description></description>
<lastBuildDate>Sat, 27 May 2023 20:21:57 +0800</lastBuildDate>
<pubDate>Sat, 27 May 2023 20:21:57 +0800</pubDate>
<item>
<title>Java浅拷贝和深拷贝</title>
<link>https://blog.anlucky.cn/index.php/programming/java/167</link>
<guid>https://blog.anlucky.cn/index.php/programming/java/167</guid>
<pubDate>Sat, 27 May 2023 20:21:57 +0800</pubDate>
<dc:creator>都依凡</dc:creator>
<description><![CDATA[浅拷贝和深拷贝参考资料：Java深拷贝和浅拷贝 - 掘金 (juejin.cn)浅拷贝与深拷贝 - 掘金 (juejin.cn)4.1 什么是浅拷贝？什么是深拷贝？浅拷贝：浅拷贝是创建一个新对象...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<h1>浅拷贝和深拷贝</h1><p>参考资料：</p><ul><li><a href="https://juejin.cn/post/6844903806577164302">Java深拷贝和浅拷贝 - 掘金 (juejin.cn)</a></li><li><a href="https://juejin.cn/post/6844904197595332622">浅拷贝与深拷贝 - 掘金 (juejin.cn)</a></li></ul><h2>4.1 什么是浅拷贝？什么是深拷贝？</h2><ul><li>浅拷贝：浅拷贝是创建一个新对象，这个对象有着原始属性值的一份精确拷贝，如果是基本数据类型，拷贝的就是基本数据类型的值，如果是深拷贝，拷贝的就是内存地址。所以<strong>如果浅拷贝的对象或者对象本身改变了属性或者值那么也会影响另一个对象</strong></li><li>深拷贝：深拷贝是将这个对象完整的拷贝下来，从内存空间中开辟一个新的地址来存放这个新对象，所以<strong>深拷贝创建的对象在改变值之后不会对另一个对象产生影响</strong></li></ul><pre><code>浅拷贝只复制指向某个对象的指针，而不复制对象本身，新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象，新对象跟原对象不共享内存，修改新对象不会改到原对象。</code></pre><h2>4.2 赋值和深拷贝，浅拷贝的区别？</h2><ul><li>赋值：当我们把一个对象赋值给另一个变量引用时，会把这个对象在栈内存中的地址给这个变量引用，这两个对象使用 == 进行比较返回true，这个情况下，不管哪个对象发生改变，改变的都是存储空间中同一块内存地址的数据，所以他们是联动的，不管改变哪个对象，另外一个对象的数据也会跟着改变。</li></ul><h3>浅克隆代码演示</h3><ul><li><p>准备实体类对象，并创建对应的get set 有参数构造和无参数构造<strong>并实现Cloneable接口中的clone方法</strong></p><ul><li>创建学生实体类</li></ul><pre><code class="lang-java">public class Student implements Cloneable{
    private int sid;
    private String sname;
    private Teacher teacher;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}</code></pre></li><li><ul><li>创建老师实体类</li></ul><pre><code class="lang-java">public class Teacher implements Cloneable{
    private Integer tid;
    private String tname;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}</code></pre></li><li><p>创建测试类Main</p><pre><code class="lang-java">public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 创建老师对象
        Teacher teacher = new Teacher();
        teacher.setTid(1);
        teacher.setTname(&quot;张老师&quot;);
        // 学生对象
        Student student = new Student();
        student.setSid(1);
        student.setSname(&quot;小明同学&quot;);
        student.setTeacher(teacher);

        // 创建学生的克隆对象   浅克隆
        Student cloneStudent = (Student) student.clone();

        System.out.println(&quot;浅克隆=》比较源对象和克隆对象  &quot; + (student == cloneStudent));
        System.out.println(&quot;浅克隆=》查询修改前源对象：&quot; + student);
        System.out.println(&quot;浅克隆=》查询修改前克隆对象：&quot; + cloneStudent);

        System.out.println(&quot;修改源对象中学生的sid属性为 2&quot;);
        student.setSid(2);
        System.out.println(&quot;修改源对象中学生的sname属性为 小红同学&quot;);
        student.setSname(&quot;小红同学&quot;);
        System.out.println(&quot;修改源对象中学生的teacher属性中的tid属性为 2&quot;);
        student.getTeacher().setTid(2);
        System.out.println(&quot;浅克隆=》查询修改后源对象：&quot; + student);
        System.out.println(&quot;浅克隆=》查询修改后克隆对象：&quot; + cloneStudent);
    }
}</code></pre><h3>输出结果</h3><pre><code>浅克隆=》比较源对象和克隆对象  false
浅克隆=》查询修改前源对象：Student(sid=1, sname=小明同学, teacher=Teacher(tid=1, tname=张老师))
浅克隆=》查询修改前克隆对象：Student(sid=1, sname=小明同学, teacher=Teacher(tid=1, tname=张老师))
修改源对象中学生的sid属性为 2
修改源对象中学生的sname属性为 小红同学
修改源对象中学生的teacher属性中的tid属性为 2
浅克隆=》查询修改后源对象：Student(sid=2, sname=小红同学, teacher=Teacher(tid=2, tname=张老师))
浅克隆=》查询修改后克隆对象：Student(sid=1, sname=小明同学, teacher=Teacher(tid=2, tname=张老师))</code></pre></li></ul><h3>浅克隆总结</h3><p>浅拷贝：拷贝前后对象的基本数据类型互不影响，但拷贝前后对象的引用类型因共享同一块内存，会相互影响。</p><p>浅拷贝是创建一个新对象，这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型，拷贝的就是基本类型的值，如果属性是引用类型，拷贝的就是内存地址 ，所以<strong>如果其中一个对象改变了这个地址，就会影响到另一个对象</strong>。</p><h3>深克隆代码演示</h3><p>深拷贝：从堆内存中开辟一个新的区域存放新对象，对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。</p><ul><li><ul><li>创建学生实体类</li></ul><pre><code class="lang-java">public class Student implements Cloneable{
    private int sid;
    private String sname;
    private Teacher teacher;
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new Student(sid,sname,new Teacher(teacher.getTid(),teacher.getTname()));
    }
}</code></pre></li><li><ul><li>创建老师实体类</li></ul><pre><code class="lang-java">public class Teacher implements Cloneable{
    private Integer tid;
    private String tname;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new Teacher(tid,this.tname);
    }
}</code></pre></li><li>创建测试类</li><li><pre><code class="lang-java">public class Main2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 创建老师对象
        Teacher teacher = new Teacher();
        teacher.setTid(1);
        teacher.setTname(&quot;张老师&quot;);
        // 学生对象
        Student student = new Student();
        student.setSid(1);
        student.setSname(&quot;小明同学&quot;);
        student.setTeacher(teacher);

        // 创建学生的克隆对象   浅克隆
        Student cloneStudent = (Student) student.clone();

        System.out.println(&quot;深克隆=》比较源对象和克隆对象  &quot; + (student == cloneStudent));
        System.out.println(&quot;深克隆=》比较源对象和克隆对象的自定义引用数据类型  &quot; + (student.getTeacher() == cloneStudent.getTeacher()));
        System.out.println(&quot;深克隆=》查询修改前源对象：&quot; + student);
        System.out.println(&quot;深克隆=》查询修改前克隆对象：&quot; + cloneStudent);

        System.out.println(&quot;修改源对象中学生的sid属性为 2&quot;);
        student.setSid(2);
        System.out.println(&quot;修改源对象中学生的sname属性为 小红同学&quot;);
        student.setSname(&quot;小红同学&quot;);
        System.out.println(&quot;修改源对象中学生的teacher属性中的tid属性为 2&quot;);
        student.getTeacher().setTid(2);
        System.out.println(&quot;深克隆=》查询修改后源对象：&quot; + student);
        System.out.println(&quot;深克隆=》查询修改后克隆对象：&quot; + cloneStudent);
    }
}</code></pre></li><li><h3>输出结果</h3><pre><code>深克隆=》比较源对象和克隆对象  false
深克隆=》比较源对象和克隆对象的自定义引用数据类型  false
深克隆=》查询修改前源对象：Student(sid=1, sname=小明同学, teacher=Teacher(tid=1, tname=张老师))
深克隆=》查询修改前克隆对象：Student(sid=1, sname=小明同学, teacher=Teacher(tid=1, tname=张老师))
修改源对象中学生的sid属性为 2
修改源对象中学生的sname属性为 小红同学
修改源对象中学生的teacher属性中的tid属性为 2
深克隆=》查询修改后源对象：Student(sid=2, sname=小红同学, teacher=Teacher(tid=2, tname=张老师))</code></pre></li></ul><pre><code>
### 深克隆总结

深拷贝：深拷贝会创建一个新的对象，将源对象的属性值放入到新对象，是创建对象赋值，并不是将引用地址指向原来的对象，所以我们在上面测试代码中可以发现深拷贝后的Teacher对象中的源对象和克隆对象比较时返回false，当一个值做更改的时候也不会影响另外一个对象
</code></pre>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.anlucky.cn/index.php/programming/java/167#comments</comments>
<wfw:commentRss>https://blog.anlucky.cn/index.php/feed/tag/Java%E9%9D%A2%E8%AF%95%E9%A2%98/</wfw:commentRss>
</item>
<item>
<title>String,StringBuffer,StringBuilder的区别</title>
<link>https://blog.anlucky.cn/index.php/programming/java/165</link>
<guid>https://blog.anlucky.cn/index.php/programming/java/165</guid>
<pubDate>Sat, 27 May 2023 20:19:00 +0800</pubDate>
<dc:creator>都依凡</dc:creator>
<description><![CDATA[可变性String是final修饰的，他是一个不可变的类，他在每次创建字符串的时候是新建了一个对象，StringBuffer和StringBuilder是一个可变的类，他在每次更改的时候会在源对...]]></description>
<content:encoded xml:lang="zh-CN"><![CDATA[
<ol><li>可变性</li></ol><p>String是final修饰的，他是一个不可变的类，他在每次创建字符串的时候是新建了一个对象，StringBuffer和StringBuilder是一个可变的类，他在每次更改的时候会在源对象的基础上更改，并不会重新创建对象</p><ol start="2"><li>线程安全性</li></ol><p>String是一个不可变的类，所以他是一个线程安全的，StringBuffer也是一个线程安全的，他的每一个方法都用了一个Synchronized一个同步关键字修饰，StringBuider不是一个线程安全的，多线程的情况下应该使用StirngBuffer</p><ol start="3"><li>性能方面</li></ol><p>String是性能最低的，因为他是不可变的类，每次修改都是创建对象，StringBuffer是可变的，每次字符串修改或者拼接的时候他不会重新创建对象，StringBuider的性能是最高的，因为StringBuffer是加了锁的，加锁之后性能方面会有所损耗</p><ol start="4"><li>存储方面</li></ol><p>String存储在字符串常量池中，StringBuffer和StringBuilder是存储在堆内存中</p>
]]></content:encoded>
<slash:comments>0</slash:comments>
<comments>https://blog.anlucky.cn/index.php/programming/java/165#comments</comments>
<wfw:commentRss>https://blog.anlucky.cn/index.php/feed/tag/Java%E9%9D%A2%E8%AF%95%E9%A2%98/</wfw:commentRss>
</item>
</channel>
</rss>