think in java第十二章笔记

本文深入探讨Java中对象复制与克隆的概念、原理及应用,包括浅层复制、深层复制、本地副本的使用场景,以及如何实现对象的复制和克隆,特别关注clone()方法的使用和限制。

1.

public class Alias2 {
	int i;
	Alias2(int ii) {
		i = ii;
	}
	static void f(Alias2 handle) {
		handle.i++;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Alias2 x = new Alias2(7);
		System.out.println("x:"+x.i);
		System.out.println("Calling f(x)");
		f(x);
		System.out.println("x:"+x.i);
	}

}

若需要在一个方法调用期间修改一个参数,且不打算修改外部参数,就应在自己的方法内部制作一个副本,从而保护那个参数。

不存在本地对象,只有本地句柄。然而有时仍需将对象当做“本地的”对待,使我们做出的改变只影响一个本地副本,不会对外面的对象造成影响。


2.若需修改一个对象,同时不想改变调用者的对象,就要制作对象的一个副本。只需要简单的使用clone()方法即可。这个方法在基础类Object中定义成"protected"模式。但在希望克隆的任何衍生类中,必须将其覆盖为"public"模式。


3.

import java.util.*;

class Int {
	private int i;
	public Int(int ii) {
		i = ii;
	}
	public void increment() {
		i++;
	}
	public String toString() {
		return Integer.toString(i);
	}
}
public class Cloning {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Vector v = new Vector();
		
		for(int i = 0; i < 10; i++)
			v.addElement(new Int(i));
		
		System.out.println("v: "+v);
		
		Vector v2 = (Vector)v.clone();
		for(Enumeration e = v2.elements(); e.hasMoreElements(); ((Int)e.nextElement()).increment());
		System.out.println("v: "+v);
	}

}

clone()方法产生了一个Object,后者必须立即重新造型为正确类型。这个例子指出Vector的clone()方法不能自动尝试克隆Vector内包含的每个对象——由于别名问题,老的Vector和克隆的Vector都包含了相同的对象。这种情况叫做“简单复制”或者“浅层复制”,因为它只复制了一个对象的“表面”部分。实际对象除包含这个“表面”以外,还包括句柄指向的所有对象。


4.

尽管克隆方法是在所有类基本的Object中定义的,但克隆仍然不会在每个类里自动进行。这似乎有些不可思议,因为基础类方法在衍生类里是肯定能用的。如果想在一个类里使用克隆方法,唯一的办法就是专门添加一些代码,以保证克隆的正常进行。

为避免我们创建的每个类都默认具有克隆能力,clone()方法在基础类Object里得到了“保留”(设为protected)。


5.

import java.util.*;
class MyObject implements Cloneable {
	int i;
	MyObject(int ii) {
		i = ii;
	}
	public Object clone() {
		Object o = null;
		
		try {
			o = super.clone();
		}catch(CloneNotSupportedException e) {
			System.out.println("MyObject can't clone");
		}
		
		return o;
	}
	
	public String toString() {
		return Integer.toString(i);
	}
}
public class LocalCopy {
	static MyObject g(MyObject v) {
		v.i++;
		return v;
	}
	static MyObject f(MyObject v) {
		v = (MyObject)v.clone();
		v.i++;
		return v;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyObject a = new MyObject(11);
		MyObject b = g(a);
		
		if(a == b)
			System.out.println("a == b");
		else
			System.out.println("a != b");
		
		System.out.println("a = "+a);
		System.out.println("b = "+ b);
		
		MyObject c = new MyObject(47);
		MyObject d = f(c);
		
		if(c == d)
			System.out.println("c == d");
		else
			System.out.println("c != d");
		
		System.out.println("c = "+c);
		System.out.println("d = "+d);
	}

}

不管怎样,clone()必须能够访问,所以必须将其设为public。其次,作为clone()的初期行动,应调用clone()的基础版本。这里调用的clone()是Object内部预先定义好的。之所以能够调用它,是由于它具有protected属性,所以能在衍生的类访问。

Object.clone()会先检查原先的对象有多大,再为新对象腾出足够多的内存,将所有二进制位从原来的对象复制到新的对象。这叫做按位复制,而且按一般的想法,这个工作应该由clone()方法来做。

在Object.clone()正式开始操作前,首先会检查一个类是否实现了Cloneable接口。若未实现,Object.clone()就抛出一个异常,指出我们不能克隆它。


6.

根类中的clone()方法负责建立正确的存储容量,并通过“按位复制”将二进制位从原始对象中复制到新对象的存储空间。  实际需要调查出欲复制之对象的准确大小,然后复制那个对象。这个过程需要RTTI判断克隆的对象的实际大小。采用这种方式,clone()方法便可建立起正确数量的存储空间,并对那个类型进行正确的按位复制。

不管我们要做什么,克隆过程的第一个部分通常都应该是采用super.clone().通过进行一次准确的复制,这样做可为后续的克隆进程建立起一个良好的基础。随后,可采取另一些必要的操作,以完成最终的克隆。


7.

import java.util.*;
class DepthReading implements Cloneable {
	private double depth;
	public DepthReading(double depth) {
		this.depth = depth;
	}
	public Object clone() {
		Object o = null;
		try {
			o = super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		return o;
	}
}

class TemperatureReading implements Cloneable {
	private long time;
	private double temperature;
	public TemperatureReading(double temperature) {
		time = System.currentTimeMillis();
		this.temperature = temperature;
	}
	public Object clone() {
		Object o = null;
		
		try {
			o = super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		return o;
	}
}

class OceanReading implements Cloneable {
	private DepthReading depth;
	private TemperatureReading temperature;
	public OceanReading(double tdata, double ddata) {
		temperature = new TemperatureReading(tdata);
		depth = new DepthReading(ddata);
	}
	public Object clone() {
		OceanReading o = null;
		
		try {
			o = (OceanReading)super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		o.depth = (DepthReading)o.depth.clone();
		o.temperature = (TemperatureReading)o.temperature.clone();
		
		return o;
	}
}
public class DeepCopy {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		OceanReading reading = new OceanReading(33.9, 100.5);
		OceanReading r = (OceanReading)reading.clone();
	}

}

通常可在一个能克隆的类里调用super.clone(),以确保所有基础类行动(包括Object.clone())能够进行。随后是为对象内每个句柄都明确调用一个clone();否则那些句柄会别名变成原始对象的句柄。构建器的调用也大致相同——首先构造基础类,然后是下一个衍生的构建器......以此类推,直到位于最深层的衍生构建器。区别在于clone()并不是构建器,所以没有办法实现自动克隆。为了克隆,必须由自己明确进行。

试图深层复制合成对象时会遇到一个问题。必须假定成员对象中的clone()方法也能依次对自己的句柄进行深层复制,依此类推。

OceanReading是由DepthReading和TemperatureReading对象合成而成的。为了对其进行深层复制,clone()必须同时克隆OceanReading内的句柄。为达到这个目标,super.clone()的结果必须造型成一个OceanReading对象(以便访问depth和temperature句柄).


8.

class Int2 implements Cloneable {
	private int i;
	public Int2(int ii) {
		i = ii;
	}
	public void increment() {
		i++;
	}
	public String toString() {
		return Integer.toString(i);
	}
	
	public Object clone() {
		Object o = null;
		try {
			o = super.clone();
		}catch(CloneNotSupportedException e) {
			System.out.println("Int2 can't clone");
		}
		return o;
	}
}

class Int3 extends Int2 {
	private int j;
	public Int3(int i) {
		super(i);
	}
}
public class AddingClone {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Int2 x = new Int2(10);
		Int2 x2 = (Int2)x.clone();
		x2.increment();
		
		System.out.println("x = "+x+", x2 = "+x2);
		Int3 x3 = new Int3(7);
		x3 = (Int3)x3.clone();
		
		Vector v = new Vector();
		for(int i = 0; i < 10; i++) {
			v.addElement(new Int2(i));
		}
		
		System.out.println("v: "+v);
		
		Vector v2 = (Vector)v.clone();
		for(int i = 0; i < v.size(); i++)
			v2.setElementAt(((Int2)v2.elementAt(i)).clone(), i);
		
		for(Enumeration e = v2.elements(); e.hasMoreElements();)
			((Int2)e.nextElement()).increment();
		System.out.println("v: "+v);
		System.out.println("v2: "+v2);
	}

}

Int3自Int2继承而来,并添加了一个新的基本类型成员int j。将Int2的clone()当做Int3的clone()调用时,它会调用Object.clone(),判断出当前操作的是Int3,并复制Int3内的所有二进制位。只要没有新增需要克隆的句柄,对Object.clone()的一个调用就能完成所有必要的复制——无论clone()是在层次结构多深的一级定义的。

对Vector进行深层复制的先决条件:在克隆了Vector后,必须在其中遍历,并克隆由Vector指向的每个对象。为了对Hashtable进行深层复制,也必须采取类似的处理。


9.

若在一个对象序列化以后再撤销对它的序列化,或者进行装配,那么实际经历的正是一个"克隆"的过程。


10.

public class Stringer {
	static String upcase(String s) {
		return s.toUpperCase();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String q = new String("howdy");
		System.out.println(q);
		String qq = upcase(q);
		System.out.println(qq);
		System.out.println(q);
	}

}
q传递进入upcase()时,它实际是q的句柄的一个副本。该句柄连接的对象实际只在一个统一的物理位置处。句柄四处传递的时候,它的句柄就会得到复制。s只有在upcase()执行期间才会存在。upcase()完成后,本地句柄s便会消失,而upcase返回结果——还是原来那个字串,只是所有字符都变成了大写。当然,它返回的实际是结果的一个句柄。但它返回的句柄最终句柄最终是为一个新对象。


String类的对象被设计成“不可变”,就会发现类中能够修改String的每个方法都实际都创建和返回了一个崭新的String对象,新对象里包含了修改过的信息——原来的String是原封未动的。


由于String对象是不可变的,所以能根据情况对一个特定的String进行多次别名处理。因为它是只读的,所以一个句柄不可能会改变一些会影响其他句柄的东西。

对字符串来说,同志类叫做StringBuffer,


<think>好的,我现在需要处理用户关于Spring Boot和Vue结合的读书笔记或学习资料的请求。用户已经提供了三个引用内容,我需要仔细分析这些引用来提取有用的信息,并结合自己的知识库来整理合适的回答。 首先,用户提到的引用1是《Spring Boot+Vue全栈开发实战》的读书笔记,里面提到了书的章节内容,包括缓存、安全管理、WebSocket、消息服务等。这些章节可以作为学习Spring Boot的重点内容。引用2是关于Vue生命周期的内容,属于前端部分,可能涉及Vue的基础知识和路由配置。引用3是关于若依框架的笔记,提到了项目结构、启动类、通用包等,这可能对实际项目搭建有帮助。 用户的需求是查找Spring Boot和Vue结合的读书笔记或学习资料,可能需要结构化的学习路径和实战项目参考。根据引用内容,我应该整理出书籍推荐、关键知识点、项目结构解析、学习路径建议以及相关资源推荐。同时,用户示例中的相关问题部分需要生成相关问题,可能涉及技术选型、项目结构、权限控制、前后端通信等。 需要注意回答的结构清晰,分点说明,并确保引用的正确标注。另外,需要验证引用中的信息是否准确,例如若依框架的结构是否如引用3所述,以及书籍的章节内容是否覆盖了用户所需的核心知识点。如果有不确定的地方,可能需要提示用户参考更多资料或官方文档。 最后,生成的相关问题应围绕Spring Boot和Vue整合的难点、技术选型、项目优化等方面,帮助用户深入学习和解决问题。确保回答符合用户的要求,使用中文,正确使用LaTeX格式,并且自然添加引用标识。</think>根据参考资料整理Spring Boot与Vue整合的读书笔记框架如下: ### 一、全栈开发核心知识结构 1. **Spring Boot核心技术** - 自动配置原理与启动流程$$@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan$$ - 安全框架整合(引用[1]第十章) - WebSocket实时通信实现(引用[1]第十一章) - 缓存机制整合Redis(引用[1]第九章) 2. **Vue核心特性** - 组件化开发模式 - Vue生命周期详解(引用[2]) - Vue Router动态路由配置(引用[2]) ### 二、典型项目架构解析(以若依框架为例) ```text ruoyi-ui/ # Vue前端项目 ├── src/ │ ├── api/ # 接口定义 │ ├── assets/ # 静态资源 │ └── views/ # 页面组件 ruoyi-admin/ # Spring Boot后端 ├── src/main/java/ │ ├── com.ruoyi.web/ # Controller层 │ ├── com.ruoyi.common/ # 工具类与通用模块(引用[3]) │ └── com.ruoyi.system/ # 业务逻辑层 ``` (项目结构参考引用[3]) ### 三、整合关键步骤 1. **前后端分离配置** - 跨域解决方案:CORS配置类 ```java @Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST"); } }; } } ``` 2. **数据交互规范** - 统一响应格式$$ResponseEntity<T> = \{ code: number, data: T, msg: string \}$$ ### 四、学习路径建议 1. **基础阶段**(2周) - Spring Boot自动装配原理 - Vue响应式原理 2. **进阶阶段**(3周) - 权限控制实现(引用[3]权限相关controller) - 微服务架构改造(引用[1]第十三章) 3. **实战阶段** - 企业级项目构建(引用[1]第十六章) - 持续集成部署(引用[1]第十五章) ### 五、推荐资源清单 | 资源类型 | 推荐内容 | |---------|----------| | 书籍 | 《Spring Boot+Vue全栈开发实战》项目部署章节(引用[1]第十五章)| | 视频 | 若依框架官方部署教程 | | 工具 | IDEA+VSCode+Postman开发套件 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值