java prototype是什么,java设计模式-原型模式(Prototype)

定义

原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。这就是原型模式的用意

原型模式的结构

原型模式要求对象实现同一个可以“克隆”自身的接口,遮掩个就可以通过赋值一个实例对象本身来创建一个新的实例。

这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法获取新的对象,而无需再去通过new来创建。

原型对象有两种表现形式:

简单形式

登记形式

这两种形式仅仅是原型模式的不同实现。

简单形式的原型模式

565aecb26f9c

原型模式

原型模式涉及三个角色:

客户(Client)角色:客户类提出创建对象的请求。

抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或者Java抽象类实现。此角色给出所有的具体原型类所需的接口。

具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象原型角色要求的接口。

示例代码

抽象原型角色

/**

* 抽象原型角色

*/

public abstract class Prototype {

private String id;

public Prototype(String id) {

this.id = id;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

/**

* 克隆自身的方法

* @return 一个从自身克隆出来的对象。

*/

public abstract Prototype clone();

}

具体原型角色

public class ConcreteProtype1 extends Prototype {

public ConcreteProtype1(String id) {

super(id);

}

public Prototype clone() {

Prototype prototype = new ConcreteProtype1(this.getId());

return prototype;

}

}

public class ConcreteProtype2 extends Prototype {

public ConcreteProtype2(String id) {

super(id);

}

public Prototype clone() {

Prototype prototype = new ConcreteProtype2(this.getId());

return prototype;

}

}

客户端

public class Client {

public static void main(String[] args) {

ConcreteProtype1 protype1 = new ConcreteProtype1("Protype1");

ConcreteProtype1 protypeCopy1 = (ConcreteProtype1)protype1.clone();

System.out.println(protypeCopy1.getId());

System.err.println(protype1.toString());

System.err.println(protypeCopy1.toString());

ConcreteProtype2 protype2 = new ConcreteProtype2("Protype2");

ConcreteProtype2 protypeCopy2 = (ConcreteProtype2)protype2.clone();

System.out.println(protypeCopy2.getId());

System.err.println(protype2.toString());

System.err.println(protypeCopy2.toString());

}

}

输出结果:

Protype1

com.sschen.prototype.ConcreteProtype1@2a139a55

com.sschen.prototype.ConcreteProtype1@15db9742

Protype2

com.sschen.prototype.ConcreteProtype2@6d06d69c

com.sschen.prototype.ConcreteProtype2@7852e922

还有另外一种对象的复制方式,如下:

ConcreteProtype1 protype3 = new ConcreteProtype1("Protype3");

ConcreteProtype1 protypeCopy3 = protype3;

System.out.println(protypeCopy3.getId());

System.err.println(protype3.toString());

System.err.println(protypeCopy3.toString());

这种方式的输出结果为:

Protype3

com.sschen.prototype.ConcreteProtype1@2a139a55

com.sschen.prototype.ConcreteProtype1@2a139a55

这种方式同上面的原型模式的克隆模式比较,可以看见的是:原型模式生成的两个对象,内存地址是不一样的。

之前在java面试 内存中堆和栈的区别文章中说明过:对象的值存放在堆中,在栈中存储指向堆中内存位置的引用。

第一种方式中,我们是重新创建了新的对象,对象的值和引用都是新的,对于克隆对象的任何变更,都不会影响到原对象的值。如下图:

565aecb26f9c

原型模式存储结构图

另一种方式,我们只是在栈中新创建了一个引用,指向的还是被复制对象对应的堆地址,对于复制对象的变更,都会同时改变原对象的值。如下图:

565aecb26f9c

不正确的对象复制方式

登记形式的原型模型

565aecb26f9c

登记形式的原型模型

作为原型模式的第二种形式,它多了一个原型管理器(PrototypeManager)角色。该角色的作用是:创建具体有原型类的对象,并记录每一个被创建的对象。

示例代码

抽象原型角色

public interface Prototype {

public Prototype clone();

public String getName();

public void setName(String name);

}

具体原型角色

public class ConcretePrototype1 implements Prototype {

private String name;

@Override

public Prototype clone() {

ConcretePrototype1 prototype1 = new ConcretePrototype1();

prototype1.setName(this.name);

return prototype1;

}

@Override

public String getName() {

return this.name;

}

@Override

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "ConcretePrototype1 [name=" + name + "]";

}

}

public class ConcretePrototype2 implements Prototype {

private String name;

@Override

public Prototype clone() {

ConcretePrototype2 prototype2 = new ConcretePrototype2();

prototype2.setName(this.name);

return prototype2;

}

@Override

public String getName() {

return this.name;

}

@Override

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "ConcretePrototype2 [name=" + name + "]";

}

}

原型管理器角色保持一个聚集,作为对所有原型对象的登记,这个角色提供必要的方法,供外界增加新的原型对象和取得已经登记过的原型对象。

public class PrototypeManager {

/**

* 用来记录原型的编号同原型实例的对象关系

*/

private static Map map = new HashMap();

/**

* 私有化构造方法,避免从外部创建实例

*/

private PrototypeManager() {}

/**

* 向原型管理器里面添加或者修改原型实例

* @param prototypeId 原型编号

* @param prototype 原型实例

*/

public synchronized static void setPrototype(String prototypeId, Prototype prototype) {

map.put(prototypeId, prototype);

}

/**

* 根据原型编号从原型管理器里面移除原型实例

* @param prototypeId 原型编号

*/

public synchronized static void removePrototype(String prototypeId) {

map.remove(prototypeId);

}

/**

* 根据原型编号获取原型实例

* @param prototypeId 原型编号

* @return 原型实例对象

* @throws Exception 如果根据原型编号无法获取对应实例,则提示异常“您希望获取的原型还没有注册或已被销毁”

*/

public synchronized static Prototype getPrototype(String prototypeId) throws Exception {

Prototype prototype = map.get(prototypeId);

if (prototype == null) {

throw new Exception("您希望获取的原型还没有注册或已被销毁");

}

return prototype;

}

}

客户端角色

public class Client {

public static void main(String[] args) {

try {

Prototype p1 = new ConcretePrototype1();

PrototypeManager.setPrototype("p1", p1);

//获取原型来创建对象

Prototype p3 = PrototypeManager.getPrototype("p1").clone();

p3.setName("张三");

System.out.println("第一个实例:" + p3);

//有人动态的切换了实现

Prototype p2 = new ConcretePrototype2();

PrototypeManager.setPrototype("p1", p2);

//重新获取原型来创建对象

Prototype p4 = PrototypeManager.getPrototype("p1").clone();

p4.setName("李四");

System.out.println("第二个实例:" + p4);

//有人注销了这个原型

PrototypeManager.removePrototype("p1");

//再次获取原型来创建对象

Prototype p5 = PrototypeManager.getPrototype("p1").clone();

p5.setName("王五");

System.out.println("第三个实例:" + p5);

} catch (Exception e) {

e.printStackTrace();

}

}

}

输出结果为:

第一个实例:ConcretePrototype1 [name=张三]

第二个实例:ConcretePrototype2 [name=李四]

java.lang.Exception: 您希望获取的原型还没有注册或已被销毁

at com.sschen.prototyperegist.PrototypeManager.getPrototype(PrototypeManager.java:44)

at com.sschen.prototyperegist.Client.main(Client.java:26)

两种形式的比较

简单形式和登记形式的原型模式各有其长处和短处。

如果需要创建的原型对象数据较少而且比较固定的话,可以采用第一种形式。在这种情况下,原型对象的引用可以由客户端自己保存。

如果要创建的原型对象数据不固定的话,可以采用第二种形式。在这种情况下,客户端不保存对原型对象的引用,这个任务被交给原型管理器角色。在克隆一个对象之前,客户端可以查看管理员对象是否已经有一个满足要求的原型对象。如果有,可以从原型管理器角色中取得这个对象引用;如果没有,客户端就需要自行复制此原型对象。

Java中的克隆方法

Java中的所有类都是从java.lang.Object类继承而来的,而Object类提供protected Object clone()方法对对象进行克隆复制,子类当然也可以把这个方法置换掉,提供满足自己需要的复制方法。对象的复制有一个基本问题,就是对象通常都有对其他对象的引用。当使用Object类的clone()方法来复制一个对象时,此对象对其他对象的引用也同时会被复制一份。

java语言提供的Cloneable接口只起一个作用,就是在运行时期通知Java虚拟机可以安全的在这个类上使用clone()方法。通过调用这个clone()方法可以得到一个对象的复制。由于Object类本身不实现Cloneable接口,因此如果所考虑的类没有实现Cloneable接口时,调用clone()方法会抛出CloneNotSupportedException异常。

克隆满足的条件

clone()方法将对象复制了一份并返还给了调用者。所谓“复制”的含义于clone()方法是怎么实现的含义是一样的。一般而言,clone()方法满足以下的描述:

对任何的对象x,都有x.clone() != x。换而言之,克隆对象和原对象不是同一个对象。

对任何的对象x,都有x.clone().getClass() == x.getClass()。换而言之,克隆对象同原对象的类型一致。

如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当是成立的。

在Java语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。Java语言的设计师再设计自己的clone()方法时,也应当遵守这三个条件。一般来说,上面的三个条件中的前两个是必需的,而第三个是可选的。

浅克隆和深克隆

无论你是自己实现克隆方法,还是采用Java提供的克隆方法,都存在一个浅度克隆和深度克隆的问题。

浅度克隆:只负责克隆按值传递的数据(比如基本数据类型,String类型),而不是复制它所引用的对象。换而言之,所有对其他对象的引用都仍然指向原来的对象。

深度克隆:除了浅度克隆需要克隆的值外,还负责克隆引用类型的数据。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换而言之,深度克隆要把复制的对象所引用的对象都复制一遍,而这种对被引用到的对象的复制叫做简间接复制。

深度克隆要深入到多少层,是一个不易确定的问题。在决定以深度克隆的方式复制一个对象的时候,必须决定对间接复制的对象是采取浅度克隆还是继续采用深度克隆。因此,在采用深度克隆时,需要决定多深才算深。

此外,在深度克隆的过程中,很可能会出现循环引用的问题,必须小心处理。

使用序列化实现深度克隆

把对象写到流里的过程是序列化Serialization的过程;而把对象从流中读出来的过程叫反序列化Deserialization过程。应当指出的是,写到流里的是对象的一个拷贝,原对象仍然存在于JVM中。

在Java语言里深度克隆一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上对象的拷贝)写到一个流里(序列化过程),再从流里读出来(反序列化过程),便可以重建对象。

public Object deepClone() throws IOException, ClassNotFoundException{

//将对象写到流里

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(this);

//从流里读回来

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());

ObjectInputStream ois = new ObjectInputStream(bis);

return ois.readObject();

}

这样做的前提就是对象及对象内部所有引用到的对象都是可序列化的,否则,就需要仔细考察那些不可序列化的对象是否可以设置成transient,从而将至排除在复制过程之外。

浅度克隆显然比深度克隆更容易实现,因为Java语言的所有类都会继承一个clone()方法,而这个clone()方法所做的正是浅度克隆。

有一些对象,比如线程Thread对象或者Socket对象,是不能简单复制或者共享的。不管是使用浅度克隆还是使用深度克隆,只要涉及这样的间接对象,就必须把简介对象射程transient而不予复制;或者由程序自行创建出相当的同等对象,权且当做复制件使用。

孙大圣的身外身法术

孙大圣的身外身本领如果在Java语言里使用原型模式来实现的话,会怎么样呢?

首先,齐天大圣The Greatest Sage,即TheGreatestSage类扮演客户角色。齐天大圣持有一个猢狲Monkey的实例,而猢狲就是大圣本尊。Monkey类具有继承自java.lang.Object的clone()方法,因此,可以通过调用这个克隆方法来复制一个Monkey实例。

示例代码

大圣持有金箍棒的实例,因此这里定义了一个金箍棒的类GoldRingedStaff

/**

* 金箍棒对象

*/

public class GoldRingedStaff {

/**

* 高度

*/

private float height = 100.00f;

/**

* 半径

*/

private float radius = 10.00f;

/**

* 金箍棒变大方法

*/

public void grow() {

this.radius *= 2;

this.height *= 2;

}

/**

* 金箍棒缩小方法

*/

public void shrink() {

this.radius /= 2;

this.height /= 2;

}

}

大圣本尊使用Monkey类来表示,这个类来扮演具体的原型角色:

/**

* 猕猴类,大圣本尊由猕猴类来表示

*/

public class Monkey implements Cloneable {

/**

* 身高

*/

private int height;

/**

* 体重

*/

private int weight;

/**

* 出生日期

*/

private Date birthDay;

/**

* 金箍棒

*/

private GoldRingedStaff staff;

/**

* 构造函数,指定创建事件和给定金箍棒

*/

public Monkey() {

this.birthDay = new Date();

this.staff = new GoldRingedStaff();

}

/**

* 克隆方法,直接调用接口的克隆方法

*/

public Object clone() {

Monkey temp = null;

try {

temp = (Monkey)super.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

} finally {

return temp;

}

}

public int getHeight() {

return height;

}

public void setHeight(int height) {

this.height = height;

}

public int getWeight() {

return weight;

}

public void setWeight(int weight) {

this.weight = weight;

}

public Date getBirthDay() {

return birthDay;

}

public void setBirthDay(Date birthDay) {

this.birthDay = birthDay;

}

public GoldRingedStaff getStaff() {

return staff;

}

public void setStaff(GoldRingedStaff staff) {

this.staff = staff;

}

}

孙大圣本尊则使用类TheGreatestSage来表示:

public class TheGreatestSage {

private Monkey monkey = new Monkey();

public void change() {

Monkey copyMonkey = (Monkey) monkey.clone();

System.out.println("大圣本尊的生日是:" + monkey.getBirthDay());

System.out.println("克隆大圣的生日是:" + copyMonkey.getBirthDay());

System.out.println("大圣本尊同克隆大圣是否为同一个对象:" + (monkey == copyMonkey));

System.out.println("大圣本尊持有的金箍棒 同 克隆大圣持有的金箍棒是否为同一个对象:" + (monkey.getStaff() == copyMonkey.getStaff()));

}

public static void main(String[] args) {

TheGreatestSage sage = new TheGreatestSage();

sage.change();

}

}

当运行TheGreatestSage类时,首先创建大圣本尊对象,然后浅度克隆大圣本尊对象。程序在运行时输出的信息如下:

大圣本尊的生日是:Wed Jun 28 10:19:53 CST 2017

克隆大圣的生日是:Wed Jun 28 10:19:53 CST 2017

大圣本尊同克隆大圣是否为同一个对象:false

大圣本尊持有的金箍棒 同 克隆大圣持有的金箍棒是否为同一个对象:true

可以看出,首先,复制的大圣本尊具有和原始的大圣本尊一样的birthDay,而本尊对象不相等,这表明他们二者是克隆关系;其次,复制的大圣本尊持有的金箍棒和原始大圣持有的金箍棒为同一个对象,这表明二者所持有的金箍棒为同一根,而非两根。

正如前面所述,继承自java.lang.Object类的clone()方法是浅度克隆。换而言之,齐天大圣所有化身所持有的金箍棒引用全都是指向一个对象的,这与《西游记》中描写并不一致。要想要纠正这一点,就需要考虑使用深度克隆

想要做到深度克隆,就要求所有需要复制的对象都实现java.io.Serializable接口。

实例代码,修改为深度克隆后

孙大圣的源代码

public class TheGreatestSage {

private Monkey monkey = new Monkey();

public void change() {

Monkey copyMonkey = null;

try {

copyMonkey = (Monkey) monkey.deepClone();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

System.out.println("大圣本尊的生日是:" + monkey.getBirthDay());

System.out.println("克隆大圣的生日是:" + copyMonkey.getBirthDay());

System.out.println("大圣本尊同克隆大圣是否为同一个对象:" + (monkey == copyMonkey));

System.out.println("大圣本尊持有的金箍棒 同 克隆大圣持有的金箍棒是否为同一个对象:" + (monkey.getStaff() == copyMonkey.getStaff()));

}

public static void main(String[] args) {

TheGreatestSage sage = new TheGreatestSage();

sage.change();

}

}

在大圣本尊Monkey类中,原有一个克隆方法clone(),为浅度克隆,因此新增一个方法deepClone(),为深度克隆。在deepClone()方法中,大圣本尊对象(一个拷贝)被序列化,然后又被反序列化。反序列化后的对象也就成了一个深度克隆后的对象。deepClone()方法如下:

/**

* 猕猴类,大圣本尊由猕猴类来表示

*/

public class Monkey implements Cloneable,Serializable {

//………………

/**

* 克隆方法,直接调用接口的克隆方法

*/

public Object clone() {

Monkey temp = null;

try {

temp = (Monkey)super.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

} finally {

return temp;

}

}

public Object deepClone() throws IOException, ClassNotFoundException {

//将对象写入流中

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

objectOutputStream.writeObject(this);

//将对象从流中读取回来

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);

return objectInputStream.readObject();

}

//……………………

}

对于金箍棒GoldRingedStaff类,也让其实现java.io.Serializable接口:

public class GoldRingedStaff implements Serializable {

//………………

}

修改后的代码运行结果为:

大圣本尊的生日是:Wed Jun 28 11:31:01 CST 2017

克隆大圣的生日是:Wed Jun 28 11:31:01 CST 2017

大圣本尊同克隆大圣是否为同一个对象:false

大圣本尊持有的金箍棒 同 克隆大圣持有的金箍棒是否为同一个对象:false

从运行结果可以看出,大圣的金箍棒同克隆大圣的金箍棒是不同的对象。这是因为使用了深度克隆,从而将大圣本尊所引用的对象也都复制了一遍,其中也包括金箍棒。

原型模式优缺点总结

原型模式的优点

原型模式允许在运行时动态的改变具体的实现类型。原型模式可以在运行期间,有客户来注册符合原型接口的实现类型,也可以动态的改变具体的实现类型,看起来接口没有任何变化,但是其实运行的已经是另外一个类实体了。因为克隆一个原型对象就类似于实例化一个类。

原型模式的缺点

原型模式最主要的缺点是每一个类都必须要配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说并不是很难,但是对于已有的类来说并不容易,可别是当一个类引用不支持序列化的间接对象,或者引用含有循环结构的时候。

参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339309.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows 动态链接库 DLL 浅析

一、概念DLL:Dynamic Link Library,即动态链接库,这种库包含了可由多个程序同时使用的代码和数据。它是microsoft在windows操作系统中实现共享函数库概念的一种实现方式。其中windows中 一些作为DLL实现的文件有:ActiveX控件&…

图片大小 媒体大小自适应_自适应堆大小

图片大小 媒体大小自适应在改进测试平台以改进Plumbr GC问题检测器的同时 ,我最终编写了一个小型测试用例,我认为这对于更广泛的读者来说可能很有趣。 我追求的目标是测试JVM在eden,survivor和Tenured空间之间如何分割堆方面的自适应性。 测…

如何优雅的激怒C/C++程序员

一、想知道怎么激怒C/C程序员及爱好者吗?那就来一起看看吧:C是一个编译很快,但运行很慢的语言。对此我不接受反驳,C我早就精通了。你问我需要多久才能精通,只要14天。前13天学C,最后1天看看面向对象就行。C…

java xml格式打包,maven项目打包xml没有被打包解决办法 ,mybatis的xml打包

在打maven包是遇见一个问题:打完包发现src/main/java中的的mapping没有被打包进去;原因主要是mapping目录里面的文件都是xml文件并不是.java文件,而maven打包默认的src/main/java的是Java文件,它不会打包里面的xml文件&#xff0c…

老司机找BUG指南,赶紧拿走。。

一.码畜:靠编译器帮自己查语法错误消灭笔误:编写适合程序员的键盘练习if (常量变量或表达式)使用goto接力超长的if,switch连续的if还是if elseif多个条件的组合:精心的排版多重括号的匹配条件编译各种const:不要纠结各种常量了,这个世界上唯一不变的就是…

红帽 jboss_红帽JBoss BRMS和BPMS富客户端框架展示了与GWT / Errai / UberFire和AngularJS的多语言集成...

红帽 jboss上周,我发布了一个博客,重点介绍了我的演示文稿,该演示文稿展示了我们在BRMS和BPMS平台内完成的工作,Drools和jBPM项目的产品化版本所产生的丰富客户端平台。 该演示文稿是所有屏幕截图和视频,您可以在此处找…

你知道自己适合做程序员吗?

哪有什么适不适合?编码本来就不是一件复杂的事情,日常工作不就是敲码、找Bug、 跟产品经理吵架、终于下班了、回家改BUG吗?今天看到了最奇葩的辞职理由:我觉得我数学不好,我不想做编程 我坐不住,我不想做编程 我性格太活泼&…

C/C++冷门知识点你知道多少呢?

在学习C语言的过程中,我们都自己总结了一些重要的知识点,但是有些不常用的冷门知识点可能就被我们选择性忘记了,你要不要来回一下呢?1:int跟signed int是一回事,short、long亦然,但char不是。ch…

判断人物眼型matlab,怎么判断眼型和脸型?

原标题:怎么判断眼型和脸型?为了判断脸部的形状,建议从面部类型诊断的长度和比例来衡量。我们只测量2个地方的长度和宽度。长度是从眉毛位置到嘴巴的长度,宽度是以嘴巴位置为中心到两个脸颊的宽度。脸型大致分为5种类型脸型大致分…

maven 打包编译_您是否真的想加快Maven的编译/打包速度? 那么takari生命周期插件就是答案。...

maven 打包编译像你们中的许多人一样,我正在使用多模块Maven项目 。 与现有的许多系统相比,它不是一个巨大的系统,它具有15个模块,3种不同的耳朵部署,带有属性文件的大量参数化以及大约10万行Java代码。 在开发高峰期&…

C/C++制作人机猜拳小游戏

C语言学完了之后总是感觉做不出什么有意思的东西&#xff0c;今天我们就来做一个好玩的小游戏试试。#include<stdio.h> #include<time.h> #include<conio.h> #include <windows.h>void win(int a, int b); void wait(); void softgame(); void lefttim…

r 数据框选子集_在带有组合框的值列表的下拉列表中显示显示属性的子集

r 数据框选子集组合框值列表&#xff08;inputComboboxListOfValues&#xff09;应该是使用LOV的非常流行的ADF Faces组件。 坦白说&#xff0c;这是我最喜欢的值列表方法。 在这篇简短的文章中&#xff0c;我将重点介绍ADF开发人员经常忽略的一项功能。 如果默认情况下定义了L…

1024到了,默默给自己点个赞!

只有程序员才能看懂的搞笑图片写了一大堆SQL语句&#xff0c;自己都不敢相信居然运行成功了找bug给客户演示&#xff0c;我的bug没被发现正则表达式返回预期效果正则表达式没有返回预期效果上线两天了&#xff0c;客户突然要改需求&#xff0c;我去年买了个表一口气写完代码&am…

input发送a.jax_Java EE 7 / JAX-RS 2.0:具有自定义HTTP标头的简单REST API身份验证和授权...

input发送a.jax在使用已可用的HTTP协议实施Web服务时&#xff0c;REST带来了很多便利。 通过仅通过指定的URL触发GET&#xff0c;POST和其他HTTP方法&#xff0c;您将确保通过REST服务的响应来完成某些工作。 但是&#xff0c;无论REST给开发人员带来了什么便利&#xff0c;安全…

C语言的main函数,究竟有几种写法?

从学习C语言开始就一直写个一个函数&#xff0c;那么你知道它的标准写法什么什么样吗&#xff1f;main函数&#xff0c;又称主函数&#xff0c;是程序执行的起点&#xff0c;我们平时写的main函数是什么样呢&#xff1f;所以说&#xff0c;其他的写法并不符合标准&#xff0c;有…

Linux C语言结构体

前面学习了c语言的基本语法特性&#xff0c;本节进行更深入的学习。预处理程序。 编译指令: 预处理, 宏定义&#xff0c;建立自己的数据类型&#xff1a;结构体&#xff0c;联合体&#xff0c;动态数据结构c语言表达式工具 逻辑运算符&#xff1a; & | ^ ~ << >&g…

Linux C语言编程基本原理与实践

重识C语言C语言是一种通用的, 面向过程的编程语言, 在系统与应用软件的开发应用较广是人类和计算机交流的一种方式ANSI C&#xff1a; 是C语言的标准, 为了避免各开发商用的C语言语法的差异C语言的特点: 简单, 快速, 高性能, 兼容性好, 功能强大, 易于学习C语言适合做什么Linux…

listview属性_属性提取器:获取ListView即时更新其元素的最佳方法

listview属性这篇文章是关于如何处理JavaFX ListViews和TableViews的&#xff0c;以及如何通过这些控件了解所包含元素的更改内容。 我想知道为什么在相关书籍中没有找到关于以下模式的任何信息&#xff0c;因为这是一个非常关键的机制。 那里的许多帖子建议通过调用以下命令来…

30分钟了解C 11新特性

什么是C 11C 11是曾经被叫做C 0x&#xff0c;是对目前C 语言的扩展和修正&#xff0c;C 11不仅包含核心语言的新机能&#xff0c;而且扩展了C 的标准程序库&#xff08;STL&#xff09;&#xff0c;并入了大部分的C Technical Report 1&#xff08;TR1&#xff09;程序库(数学的…

外链分享已取消无法下载怎么办_微信升级外链规范:“砍一刀”、“帮我加速吧”将被封禁...

北京商报讯(记者魏蔚)朋友圈、微信群遍布的购物分享链接&#xff0c;再度受到微信严控。10月18日晚间&#xff0c;微信宣布&#xff0c;外链规范即将进行更新升级&#xff0c;新增和细化多项外链规则&#xff0c;包括不可违规使用用户头像&#xff1b;不可诱导、误导下载/跳转&…