Cloneable 接口

2024-02-21 05:08
文章标签 接口 cloneable

本文主要是介绍Cloneable 接口,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Cloneable 接口

 

·public interface Cloneable此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。

 

如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException  异常。

 

按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone(),以获得有关重写此方法的详细信息。

 

注意,此接口不 包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。

 

 

·cloneable接口是一个标志性的接口,实现他可以不实现任何方法。使用了它就标志这个类可以复制,如果想实现深层次的克隆,那就要重载clone()方法。

 

·若需要修改一个对象,同时不想改变调用者的对象,就用克隆,  
    先用implements   Cloneble实现Cloneble接口,  
    再实现clone();

 

 

·这是里面的一段(非完整的例子):  
  public   class   Snake   implements   Cloneable   {  
   
  ...........................  
   
  public   Object   clone()   {  
          Object   o   =   null;  
          try   {  
              o   =   super.clone();  
          }   catch   (CloneNotSupportedException   e)   {}  
          return   o;

 

 

·copy书上一段给你看看,希望有帮助把。。  
  当制作实例变量的一个引用时,原始实例变量和副本实力变量在内存中引用的均是同一个存储空间,这就意味着但对其中一个实例变量操作时就会影响到这个对象的副本。例如下面的程序代码。在执行时将会看到所画的两条线重合在一起,都是改变后的LineFigure1。  
  LineFigure   lineFigure1   =   new   LineFigure();  
  LineFigure   lineFigure2   =   lineFigure1;  
  lineFigure1.draw(g);  
  …code   for   changing   lineFigure1  
  lineFigure2.draw(g);  
  如果想让LineFigure2成为一个新的对象,就要用到Clone(   )方法。Clone的后对象和原对象的存储空间不同,改变其中一个并不会对另一个产生任何影响。例如下面代码所示:  
  …………….  
  LineFigure2   =   lineFigure1.clone();  
  …………….  
  如果LineFigure2中没有对其他对象的引用,事情就到此结束了,但LineFigure类中的实例变量StartPoint和EndPoint都是一个对象,即使简单地实现了对LineFigure1地Clone,可LineFigure1和LineFigure2的StartPoint和EndPoint实例变量引用的是同一个变量,要想完全的实现将LineFigure2和LineFigure1分离开,就要实现Cloneable接口,并重写Clone方法。Cloneable接口是Java提供的少数几个标签化接口之一。平常所说的标签化接口就是不提供任何方法的接口。在图形白板程序中,也用到了Cloneable接口,例如LineFigure类中的代码:  
  public   class   LineFigure   extends   Figure   implements   Cloneable{  
      public   Object   clone(){  
          LineFigure   lineFigure   =   new   LineFigure();  
          lineFigure.startPoint   =   (Point)startPoint.clone();  
          lineFigure.endPoint   =   (Point)endPoint.clone();  
          lineFigure.firstDraw   =   firstDraw;  
          return   lineFigure;  
      }  
  ………………..  
  }  
  这样一来,LineFigure1和LineFigure2所引用的对象就没有任何的重合。对其中任何一个进行修改而不影响另一个的应用。  

 

 

 

·java中的clon()和cloneable接口浅析

 

......The clone( ) method generates a duplicate copy of the object on which it is called. Only classes that implement the Cloneable interface can be cloned.

 

...clone()产生了一个调用它的对象的复制;只有实现了Cloneable接口的类才可以被复制。

 

 

The Cloneable interface defines no members. It is used to indicate that a class allows a bitwise copy of an object (that is, a clone ) to be made. If you try to call clone( ) on a class that does not implement Cloneable , a CloneNotSupportedException is thrown. When a clone is made, the constructor for the object being cloned is not called. A clone is simply an exact copy of the original.

 

Cloneable 接口没有定义任何成员。它用来指明一个类可以逐位复制一个对象。如果你试图对一个没有实现cloneable接口的类调用clone()方法,一个CloneNotSupportedException 就会抛出。在复制时,被复制的对象的构造器并没有被调用。复制对象就是原来对象的拷贝。

 

Cloning is a potentially dangerous action, because it can cause unintended side effects. For example, if the object being cloned contains a reference variable called obRef, then when the clone is made, obRef in the clone will refer to the same object as does obRef in the original. If the clone makes a change to the contents of the object referred to by obRef, then it will be changed for the original object, too. Here is another example. If an object opens an I/O stream and is then cloned, two objects will be capable of operating on the same stream. Further, if one of these objects closes the stream, the other object might still attempt to write to it, causing an error.

 

复制是一种存在潜在危险的行为,因为它会引起一些意想不到的负作用。例如,如果被复制的对象包含一个名为 obRef 引用变量,在复制时,复制对象的 obRe和f 原来对象的 obRef 都会指向同一个对象。如果复制对象对 obRef 指向的对象的内容做出一些改变,对于原来对象来说,也就相当于它也被改变了。还有另一个例子,如果一个操作I/O流的对象被复制了,这两个对象都能对同一I/O流进行操作。进一步说,如果它们两个中的一个关闭了I/O流,而另一个对象可能试图对I/O流进行写操作,这就会引起错误。

 

Because cloning can cause problems, clone( ) is declared as protected inside Object . This means that it must either be called from within a method defined by the class that implements Cloneable , or it must be explicitly overridden by that class so that it is public. Let's look at an example of each approach.

因为复制可以引起许多问题,clone()在object类中被声明为protected.这意味着,它要么在一个实现了cloneable接口的类中的某一方法里被调用,要么在明确的在那个类中的被重写,且被声明为public的。下面,我们来看一下每一种方法。

 

 

The following program implements Cloneable and defines the method cloneTest( ) , which calls clone( ) in Object :

 

// Demonstrate the clone() method.

class TestClone implements Cloneable {

int a;

double b;

// This method calls Object's clone().

TestClone cloneTest() {

try {

// call clone in Object.

return (TestClone) super.clone();

} catch(CloneNotSupportedException e) {

System.out.println("Cloning not allowed.");

return this;

}

}

}

class CloneDemo {

public static void main(String args[]) {

TestClone x1 = new TestClone();

TestClone x2;

x1.a = 10;

x1.b = 20.98;

x2 = x1.cloneTest(); // clone x1

System.out.println("x1: " + x1.a + " " + x1.b);

System.out.println("x2: " + x2.a + " " + x2.b);

}

}

 

Here, the method cloneTest( ) calls clone( ) in Object and returns the result. Notice that the object returned by clone( ) must be cast into its appropriate type (TestClone ). The following example overrides clone( ) so that it can be called from code outside of its class. To do this, its access specifier must be public , as shown here:

 

// Override the clone() method.

class TestClone implements Cloneable {

int a;

double b;

// clone() is now overridden and is public.

public Object clone() {

try {

// call clone in Object.

return super.clone();

} catch(CloneNotSupportedException e) {

System.out.println("Cloning not allowed.");

return this;

}

}

}

class CloneDemo2 {

public static void main(String args[]) {

TestClone x1 = new TestClone();

TestClone x2;

x1.a = 10;

x1.b = 20.98;

// here, clone() is called directly.

x2 = (TestClone) x1.clone();

System.out.println("x1: " + x1.a + " " + x1.b);

System.out.println("x2: " + x2.a + " " + x2.b);

}

}

 

The side effects caused by cloning are sometimes difficult to see at first. It is easy to think that a class is safe for cloning when it actually is not. In general, you should not implement Cloneable for any class without good reason.

 

以上两个程序,运行一下,便于理解。

 

以下在补充两点:

1  It is what is known as a 'marker' interface . A marker interface has no methods or fields and serves only to identify the semantics of that interface. Another example is Serializable .

2  object.clone()可能产生a shallow copy()也可能产生a deep copy.

 

 

这篇关于Cloneable 接口的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/730653

相关文章

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代