java 修改 枚举类字段_枚举枚举和修改“最终静态”字段的方法

java 修改 枚举类字段

在本新闻通讯中,该新闻通讯最初发表在Java专家的新闻通讯第161期中,我们研究了如何使用sun.reflect包中的反射类在Sun JDK中创建枚举实例。 显然,这仅适用于Sun的JDK。 如果需要在另一个JVM上执行此操作,则您可以自己完成。

所有这些都始于爱丁堡的Ken Dobson的电子邮件,该电子邮件向我指出了sun.reflect.ConstructorAccessor的方向,他声称可以将其用于构造枚举实例。 我以前的方法(通讯#141)在Java 6中不起作用。

我很好奇为什么Ken要构造枚举。 这是他想使用它的方式:

public enum HumanState {HAPPY, SAD
}public class Human {public void sing(HumanState state) {switch (state) {case HAPPY:singHappySong();break;case SAD:singDirge();break;default:new IllegalStateException("Invalid State: " + state);}}private void singHappySong() {System.out.println("When you're happy and you know it ...");}private void singDirge() {System.out.println("Don't cry for me Argentina, ...");}
}

上面的代码需要进行单元测试。 你发现错误了吗? 如果没有,请使用细梳再次遍历代码以尝试找到它。 当我第一次看到这个时,我也没有发现错误。

当我们产生这样的错误时,我们应该做的第一件事就是进行一个显示它的单元测试。 但是,在这种情况下,我们无法使default情况发生,因为HumanState仅具有HAPPY和SAD枚举。

Ken的发现使我们可以使用sun.reflect包中的ConstructorAccessor类来创建枚举的实例。 它涉及到以下内容:

Constructor cstr = clazz.getDeclaredConstructor(String.class, int.class
);
ReflectionFactory reflection =ReflectionFactory.getReflectionFactory();
Enum e =reflection.newConstructorAccessor(cstr).newInstance("BLA",3);

但是,如果仅执行此操作,则最终会出现ArrayIndexOutOfBoundsException,这在我们看到Java编译器如何将switch语句转换为字节代码时才有意义。 以上面的Human类为例,下面是反编译后的代码(感谢Pavel Kouznetsov的JAD ):

public class Human {public void sing(HumanState state) {static class _cls1 {static final int $SwitchMap$HumanState[] =new int[HumanState.values().length];static {try {$SwitchMap$HumanState[HumanState.HAPPY.ordinal()] = 1;} catch(NoSuchFieldError ex) { }try {$SwitchMap$HumanState[HumanState.SAD.ordinal()] = 2;} catch(NoSuchFieldError ex) { }}}switch(_cls1.$SwitchMap$HumanState[state.ordinal()]) {case 1:singHappySong();break;case 2:singDirge();break;default:new IllegalStateException("Invalid State: " + state);break;}}private void singHappySong() {System.out.println("When you're happy and you know it ...");}private void singDirge() {System.out.println("Don't cry for me Argentina, ...");}
}

您可以立即看到为什么要得到ArrayIndexOutOfBoundsException,这要归功于内部类_cls1。

我第一次尝试解决此问题并没有得到一个不错的解决方案。 我试图在HumanState枚举中修改$ VALUES数组。 但是,我只是摆脱了Java的保护性代码。 您可以修改final字段 ,只要它们是非静态的即可。 这种限制对我来说似乎是人为的,因此我着手寻找静态最终领域的圣杯。 再次,它被隐藏在阳光反射的房间里。

设置“最终静态”字段

设置final static字段需要几件事。 首先,我们需要使用法线反射获取Field对象。 如果将其传递给FieldAccessor,我们将退出安全代码,因为我们正在处理静态的final字段。 其次,我们将Field对象实例内的修饰符字段值更改为非最终值。 第三,我们将经过修改的字段传递给sun.reflect包中的FieldAccessor并使用它进行设置。

这是我的ReflectionHelper类,可用于通过反射设置final static字段:

import sun.reflect.*;
import java.lang.reflect.*;public class ReflectionHelper {private static final String MODIFIERS_FIELD = "modifiers";private static final ReflectionFactory reflection =ReflectionFactory.getReflectionFactory();public static void setStaticFinalField(Field field, Object value)throws NoSuchFieldException, IllegalAccessException {// we mark the field to be publicfield.setAccessible(true);// next we change the modifier in the Field instance to// not be final anymore, thus tricking reflection into// letting us modify the static final fieldField modifiersField =Field.class.getDeclaredField(MODIFIERS_FIELD);modifiersField.setAccessible(true);int modifiers = modifiersField.getInt(field);// blank out the final bit in the modifiers intmodifiers &= ~Modifier.FINAL;modifiersField.setInt(field, modifiers);FieldAccessor fa = reflection.newFieldAccessor(field, false);fa.set(null, value);}
}

通过使用ReflectionHelper,我可以在枚举中设置$ VALUES数组以包含新的枚举。 这行得通,只是我必须在首次加载Human类之前执行此操作。 这会将竞争条件引入我们的测试用例中。 单独进行每个测试都可以,但是总的来说它们可能会失败。 这不是一个好方案!

重新连接枚举开关

下一个想法是重新连接实际的switch语句的$ SwitchMap $ HumanState字段。 在匿名内部类中很容易找到此字段。 您所需要的只是前缀$ SwitchMap $,后跟枚举类名称。 如果枚举在一个类中切换了几次,则内部类仅创建一次。

我昨天写的其他解决方案之一检查了我们的switch语句是否正在处理所有可能的情况。 将新类型引入系统后,这对于发现错误很有用。 我放弃了该特定解决方案,但是您应该能够根据稍后将向您展示的EnumBuster重新创建该解决方案。

纪念品设计模式

我最近重新编写了我的设计模式课程 (警告,该网站可能尚未建立最新的结构–请查询更多信息),以考虑Java的变化,丢弃一些过时的模式并介绍我以前排除的一些。 Memento是“新”模式之一,通常与撤消功能一起使用。 我认为这是一个很好的模式,可以用来在我们努力测试不可能的案例的努力中消除对枚举的损害。

出版专家通讯给我某些自由。 我不必解释我写的每一行。 因此,事不宜迟,这里是我的EnumBuster类,它使您可以创建枚举,将它们添加到现有的values []中,从数组中删除枚举,同时保留您指定的任何类的switch语句。

import sun.reflect.*;import java.lang.reflect.*;
import java.util.*;public class EnumBuster<E extends Enum<E>> {private static final Class[] EMPTY_CLASS_ARRAY =new Class[0];private static final Object[] EMPTY_OBJECT_ARRAY =new Object[0];private static final String VALUES_FIELD = "$VALUES";private static final String ORDINAL_FIELD = "ordinal";private final ReflectionFactory reflection =ReflectionFactory.getReflectionFactory();private final Class<E> clazz;private final Collection<Field> switchFields;private final Deque<Memento> undoStack =new LinkedList<Memento>();/*** Construct an EnumBuster for the given enum class and keep* the switch statements of the classes specified in* switchUsers in sync with the enum values.*/public EnumBuster(Class<E> clazz, Class... switchUsers) {try {this.clazz = clazz;switchFields = findRelatedSwitchFields(switchUsers);} catch (Exception e) {throw new IllegalArgumentException("Could not create the class", e);}}/*** Make a new enum instance, without adding it to the values* array and using the default ordinal of 0.*/public E make(String value) {return make(value, 0,EMPTY_CLASS_ARRAY, EMPTY_OBJECT_ARRAY);}/*** Make a new enum instance with the given ordinal.*/public E make(String value, int ordinal) {return make(value, ordinal,EMPTY_CLASS_ARRAY, EMPTY_OBJECT_ARRAY);}/*** Make a new enum instance with the given value, ordinal and* additional parameters.  The additionalTypes is used to match* the constructor accurately.*/public E make(String value, int ordinal,Class[] additionalTypes, Object[] additional) {try {undoStack.push(new Memento());ConstructorAccessor ca = findConstructorAccessor(additionalTypes, clazz);return constructEnum(clazz, ca, value,ordinal, additional);} catch (Exception e) {throw new IllegalArgumentException("Could not create enum", e);}}/*** This method adds the given enum into the array* inside the enum class.  If the enum already* contains that particular value, then the value* is overwritten with our enum.  Otherwise it is* added at the end of the array.** In addition, if there is a constant field in the* enum class pointing to an enum with our value,* then we replace that with our enum instance.** The ordinal is either set to the existing position* or to the last value.** Warning: This should probably never be called,* since it can cause permanent changes to the enum* values.  Use only in extreme conditions.** @param e the enum to add*/public void addByValue(E e) {try {undoStack.push(new Memento());Field valuesField = findValuesField();// we get the current Enum[]E[] values = values();for (int i = 0; i < values.length; i++) {E value = values[i];if (value.name().equals(e.name())) {setOrdinal(e, value.ordinal());values[i] = e;replaceConstant(e);return;}}// we did not find it in the existing array, thus// append it to the arrayE[] newValues =Arrays.copyOf(values, values.length + 1);newValues[newValues.length - 1] = e;ReflectionHelper.setStaticFinalField(valuesField, newValues);int ordinal = newValues.length - 1;setOrdinal(e, ordinal);addSwitchCase();} catch (Exception ex) {throw new IllegalArgumentException("Could not set the enum", ex);}}/*** We delete the enum from the values array and set the* constant pointer to null.** @param e the enum to delete from the type.* @return true if the enum was found and deleted;*         false otherwise*/public boolean deleteByValue(E e) {if (e == null) throw new NullPointerException();try {undoStack.push(new Memento());// we get the current E[]E[] values = values();for (int i = 0; i < values.length; i++) {E value = values[i];if (value.name().equals(e.name())) {E[] newValues =Arrays.copyOf(values, values.length - 1);System.arraycopy(values, i + 1, newValues, i,values.length - i - 1);for (int j = i; j < newValues.length; j++) {setOrdinal(newValues[j], j);}Field valuesField = findValuesField();ReflectionHelper.setStaticFinalField(valuesField, newValues);removeSwitchCase(i);blankOutConstant(e);return true;}}} catch (Exception ex) {throw new IllegalArgumentException("Could not set the enum", ex);}return false;}/*** Undo the state right back to the beginning when the* EnumBuster was created.*/public void restore() {while (undo()) {//}}/*** Undo the previous operation.*/public boolean undo() {try {Memento memento = undoStack.poll();if (memento == null) return false;memento.undo();return true;} catch (Exception e) {throw new IllegalStateException("Could not undo", e);}}private ConstructorAccessor findConstructorAccessor(Class[] additionalParameterTypes,Class<E> clazz) throws NoSuchMethodException {Class[] parameterTypes =new Class[additionalParameterTypes.length + 2];parameterTypes[0] = String.class;parameterTypes[1] = int.class;System.arraycopy(additionalParameterTypes, 0,parameterTypes, 2,additionalParameterTypes.length);Constructor<E> cstr = clazz.getDeclaredConstructor(parameterTypes);return reflection.newConstructorAccessor(cstr);}private E constructEnum(Class<E> clazz,ConstructorAccessor ca,String value, int ordinal,Object[] additional)throws Exception {Object[] parms = new Object[additional.length + 2];parms[0] = value;parms[1] = ordinal;System.arraycopy(additional, 0, parms, 2, additional.length);return clazz.cast(ca.newInstance(parms));}/*** The only time we ever add a new enum is at the end.* Thus all we need to do is expand the switch map arrays* by one empty slot.*/private void addSwitchCase() {try {for (Field switchField : switchFields) {int[] switches = (int[]) switchField.get(null);switches = Arrays.copyOf(switches, switches.length + 1);ReflectionHelper.setStaticFinalField(switchField, switches);}} catch (Exception e) {throw new IllegalArgumentException("Could not fix switch", e);}}private void replaceConstant(E e)throws IllegalAccessException, NoSuchFieldException {Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (field.getName().equals(e.name())) {ReflectionHelper.setStaticFinalField(field, e);}}}private void blankOutConstant(E e)throws IllegalAccessException, NoSuchFieldException {Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (field.getName().equals(e.name())) {ReflectionHelper.setStaticFinalField(field, null);}}}private void setOrdinal(E e, int ordinal)throws NoSuchFieldException, IllegalAccessException {Field ordinalField = Enum.class.getDeclaredField(ORDINAL_FIELD);ordinalField.setAccessible(true);ordinalField.set(e, ordinal);}/*** Method to find the values field, set it to be accessible,* and return it.** @return the values array field for the enum.* @throws NoSuchFieldException if the field could not be found*/private Field findValuesField()throws NoSuchFieldException {// first we find the static final array that holds// the values in the enum classField valuesField = clazz.getDeclaredField(VALUES_FIELD);// we mark it to be publicvaluesField.setAccessible(true);return valuesField;}private Collection<Field> findRelatedSwitchFields(Class[] switchUsers) {Collection<Field> result = new ArrayList<Field>();try {for (Class switchUser : switchUsers) {Class[] clazzes = switchUser.getDeclaredClasses();for (Class suspect : clazzes) {Field[] fields = suspect.getDeclaredFields();for (Field field : fields) {if (field.getName().startsWith("$SwitchMap$" +clazz.getSimpleName())) {field.setAccessible(true);result.add(field);}}}}} catch (Exception e) {throw new IllegalArgumentException("Could not fix switch", e);}return  result;}private void removeSwitchCase(int ordinal) {try {for (Field switchField : switchFields) {int[] switches = (int[]) switchField.get(null);int[] newSwitches = Arrays.copyOf(switches, switches.length - 1);System.arraycopy(switches, ordinal + 1, newSwitches,ordinal, switches.length - ordinal - 1);ReflectionHelper.setStaticFinalField(switchField, newSwitches);}} catch (Exception e) {throw new IllegalArgumentException("Could not fix switch", e);}}@SuppressWarnings("unchecked")private E[] values()throws NoSuchFieldException, IllegalAccessException {Field valuesField = findValuesField();return (E[]) valuesField.get(null);}private class Memento {private final E[] values;private final Map<Field, int[]> savedSwitchFieldValues =new HashMap<Field, int[]>();private Memento() throws IllegalAccessException {try {values = values().clone();for (Field switchField : switchFields) {int[] switchArray = (int[]) switchField.get(null);savedSwitchFieldValues.put(switchField,switchArray.clone());}} catch (Exception e) {throw new IllegalArgumentException("Could not create the class", e);}}private void undo() throwsNoSuchFieldException, IllegalAccessException {Field valuesField = findValuesField();ReflectionHelper.setStaticFinalField(valuesField, values);for (int i = 0; i < values.length; i++) {setOrdinal(values[i], i);}// reset all of the constants defined inside the enumMap<String, E> valuesMap =new HashMap<String, E>();for (E e : values) {valuesMap.put(e.name(), e);}Field[] constantEnumFields = clazz.getDeclaredFields();for (Field constantEnumField : constantEnumFields) {E en = valuesMap.get(constantEnumField.getName());if (en != null) {ReflectionHelper.setStaticFinalField(constantEnumField, en);}}for (Map.Entry<Field, int[]> entry :savedSwitchFieldValues.entrySet()) {Field field = entry.getKey();int[] mappings = entry.getValue();ReflectionHelper.setStaticFinalField(field, mappings);}}}
}

该类很长,可能仍然存在一些错误。 我是从旧金山到纽约的途中写的。 这是我们可以使用它来测试人类班级的方法:

import junit.framework.TestCase;public class HumanTest extends TestCase {public void testSingingAddingEnum() {EnumBuster<HumanState> buster =new EnumBuster<HumanState>(HumanState.class,Human.class);try {Human heinz = new Human();heinz.sing(HumanState.HAPPY);heinz.sing(HumanState.SAD);HumanState MELLOW = buster.make("MELLOW");buster.addByValue(MELLOW);System.out.println(Arrays.toString(HumanState.values()));try {heinz.sing(MELLOW);fail("Should have caused an IllegalStateException");}catch (IllegalStateException success) { }}finally {System.out.println("Restoring HumanState");buster.restore();System.out.println(Arrays.toString(HumanState.values()));}}
}

现在,此单元测试在前面显示的Human.java文件中显示了错误。 我们忘记添加throw关键字!

When you're happy and you know it ...
Don't cry for me Argentina, ...
[HAPPY, SAD, MELLOW]
Restoring HumanState
[HAPPY, SAD]AssertionFailedError: Should have caused an IllegalStateExceptionat HumanTest.testSingingAddingEnum(HumanTest.java:23)

EnumBuster类可以做的更多。 我们可以使用它删除不需要的枚举。 如果我们指定switch语句属于哪些类,则将同时维护这些类。 另外,我们可以还原到初始状态。 很多功能!

我注销之前的最后一个测试用例,我们将测试类添加到switch类中以进行维护。

import junit.framework.TestCase;public class EnumSwitchTest extends TestCase {public void testSingingDeletingEnum() {EnumBuster<HumanState> buster =new EnumBuster<HumanState>(HumanState.class,EnumSwitchTest.class);try {for (HumanState state : HumanState.values()) {switch (state) {case HAPPY:case SAD:break;default:fail("Unknown state");}}buster.deleteByValue(HumanState.HAPPY);for (HumanState state : HumanState.values()) {switch (state) {case SAD:break;case HAPPY:default:fail("Unknown state");}}buster.undo();buster.deleteByValue(HumanState.SAD);for (HumanState state : HumanState.values()) {switch (state) {case HAPPY:break;case SAD:default:fail("Unknown state");}}buster.deleteByValue(HumanState.HAPPY);for (HumanState state : HumanState.values()) {switch (state) {case HAPPY:case SAD:default:fail("Unknown state");}}} finally {buster.restore();}}
}

EnumBuster甚至保留常量,因此,如果从values()中删除一个枚举,它将清空最终的静态字段。 如果重新添加,它将设置为新值。

肯·多布森(Ken Dobson)的想法以一种我不知道有可能的方式进行反思,真是太有趣了。 (任何Sun工程师都读过这篇文章,请不要在Java的未来版本中插入这些漏洞!)

亲切的问候

亨氏

JavaSpecialists在您公司内提供所有课程。 更多信息 …
请务必阅读我们有关Java并发性的新课程。 请与我联系以获取更多信息。

关于Heinz M. Kabutz博士

自2000年以来,我一直为Java专家社区写作。这很有趣。 当您与可能会喜欢的人分享本文时,会更加有趣。 如果他们前往www.javaspecialists.eu并将自己添加到列表中,他们可以每个月获得新鲜的东西。

中继:这篇文章是Java Advent Calendar的一部分,并根据Creative Commons 3.0 Attribution许可获得许可。 如果您喜欢它,请通过共享,发推,FB,G +等方式传播信息! 想为博客写文章吗? 我们正在寻找能够填补所有24个职位的贡献者,并希望能为您贡献力量! 联系Attila Balazs贡献力量!

参考资料:来自Java日历日历博客的JCG合作伙伴 Attila-Mihaly Balazs的“枚举枚举和修改“最终静态”字段” 。

翻译自: https://www.javacodegeeks.com/2012/12/of-hacking-enums-and-modifying-final-static-fields.html

java 修改 枚举类字段

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

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

相关文章

tf.reduce_mean

tf.reduce_mean(input_tensor, axisNone, keep_dimsFalse, nameNone, reduction_indicesNone) 作用&#xff1a;沿着张量不同的数轴进行计算平均值。 参数&#xff1a;input_tensor: 被计算的张量&#xff0c;确保为数字类型。 axis: 方向数轴&#xff0c;如果没有…

display函数怎么使用_使用网络构建复杂布局超实用的技巧,赶紧收藏吧

前端开发工程师必读书籍有哪些值得推荐&#xff1f;我们直接进入代码&#xff0c;如下所示&#xff0c;先写些标签&#xff0c;源码在这个链接里面&#xff1a;https://codepen.io/Shadid/pen/zYqNvgvHeader Aside 1 Section Aside 2 Footer在上面&#xff0c;我们创建了一…

安装后jdk1.8 配置环境变量以后 版本显示还是1.7

配置图如下 1.7版本不用卸载 不用就可以了 转载于:https://www.cnblogs.com/roujiamo/p/10836593.html

为@Cacheable设置TTL – Spring

今天&#xff0c;我被要求为应用程序正在使用的某些键设置缓存的过期时间&#xff0c;因此我Swift开始寻找Spring Cacheable表示法提供的所有选项&#xff0c;以设置过期时间或生存时间。 由于Spring没有提供任何可配置的选项来实现它&#xff0c;因此&#xff0c;我利用固定延…

tf.equal

tf.equal(A, B)是对比这两个矩阵或者向量的相等的元素&#xff0c;如果是相等的那就返回True&#xff0c;反正返回False&#xff0c;返回的值的矩阵维度和A是一样的 import tensorflow as tf import numpy as np A [[1,3,4,5,6]] B [[1,3,4,3,2]] with tf.Session() a…

校验输入框的内容不能重复_答应我,用了这个jupyter插件,别再重复造轮子了

以下文章来源于Python大数据分析 &#xff0c;作者费弗里1 简介在使用Python、R等完成日常任务的过程中&#xff0c;可能会经常书写同样或模式相近的同一段代码&#xff0c;譬如每次使用matplotlib绘制图像的时候可以在开头添加下面两行代码来解决中文乱码等显示问题&#xff1…

P2387 [NOI2014]魔法森林

和最小差值生成树差不多 都是用lct维护生成树的题目 本题可以以a排序&#xff0c;再维护b&#xff08;通常这种二维变量的题都差不多这样&#xff0c;先排序一维&#xff09; 然后我tm竟然rotate手误打错了一点...调了好久.. 然后关于pushup&#xff1a;关于最大值&#xff0c;…

C# float/double 减 float/double 等 (X.xxxxxxxxxxxxxE-07)(黑盒测试)

问题 因为没有深究原理&#xff0c;所有只进行了“黑盒测试” 黑盒测试结论&#xff1a; 问题操作结论float/double运算进过一系列的运算后大概率 &#xff01; 0.0 &#xff0c; 而是等于0.00000000000xxxx等于X.xxxxxxxx一串数字的时候不影响下一步继续使用当需要显示fl…

ABP的新旧版本

新版本 https://abp.io/documents/abp/latest/Index https://github.com/abpframework/abp ABP is an open source application framework focused on ASP.NET Core based web application development, but also supports developing other types of applications. 旧版本…

tensorflow的优化器Optimizer

种类如下&#xff0c;其中Optimizer是基类tf.train.Optimizertf.train.GradientDescentOptimizertf.train.AdadeltaOptimizertf.train.AdagradOptimizertf.train.AdagradDAOptimizertf.train.MomentumOptimizertf.train.AdamOptimizertf.train.FtrlOptimizertf.train.ProximalG…

python3支持中文_彻底颓了—— Vim Python 3 接口不支持中文 - Jacky Liu's Blog

折腾了好久才编译出来一个支持 Python 3 的 Vim&#xff0c;谁知居然有这么多问题。 除了 vim.current.buffer 对象不再支持 slice 类型参数以外&#xff0c;今天又发现这个&#xff1a; :py3 vim.current.buffer.append(XXX 模块的控制面板) 结果在 Vim 里加进去的一行看起来是…

如何处理班级过多的问题

在几乎所有我解释了 面向对象程序设计 观点的演讲中&#xff0c;都有人分享这样的评论&#xff1a;“如果我们遵循您的建议&#xff0c;我们将有很多小类。” 我的回答总是一样&#xff1a;“我们当然会的&#xff0c;那太好了&#xff01;” 老实说&#xff0c;即使您不能考虑…

java护照号码校验_学无止境之小白学java……第001天

学习主题&#xff1a;预科阶段对应视频&#xff1a;http://www.itbaizhan.cn/course/id/18.html 对应作业&#xff1a;1. 为什么需要学编程&#xff0c;什么样的人可以做程序员&#xff1f;编程是现实逻辑的表达&#xff0c;编程对数学和英语要求并不高。2. 本行不行&#xff0…

mfc通过信号量保证线程同步

1、声明一个全局handle,记住在cpp里也声明 extern HANDLE uiHandle; 2、创建信号量 uiHandle CreateSemaphore(NULL,1,1,NULL); 3、使用 线程1&#xff1a;WaitForSingleObject(uiHandle,INFINITE); a;//在这里访问同一对象 ReleaseSemaphore(uiHandle,1,NULL); 线程2&#xf…

python字典和集合双向索引_Python字典和集合

字典和集合基础字典是一系列无序元素的组合&#xff0c;其长度大小可变&#xff0c;元素可以任意的删减和改变。不过&#xff0c;这里的元素是一堆键&#xff08;key&#xff09;和值&#xff08;value&#xff09;的配对。 集合没有键和值的配对&#xff0c;是一系列无序的、唯…

ITK读取图像

//读取png图像#include "itkImage.h" #include "itkImageFileReader.h" #include "itkImageFileWriter.h" #include "itkPNGImageIOFactory.h" #include "itkJPEGImageIOFactory.h"int main(int argc, char ** argv) {typed…

documentFragment深入理解

documentFragment是一个保存多个element的容器对象&#xff08;保存在内存&#xff09;当更新其中的一个或者多个element时&#xff0c;页面不会更新。只有当documentFragment容器中保存的所有element更新后再将其插入到页面中才能更新页面。 documentFragment用来批量更新 列如…

在React中处理事件

在使用React渲染RESTful服务后&#xff0c;我们创建了一个简单的UI&#xff0c;用于渲染从RESTful服务获取的员工列表。 作为本文的一部分&#xff0c;我们将扩展同一应用程序以支持添加和删除员工操作。 我们将通过添加/删除员工操作来更新react-app后端api&#xff0c;并修改…

ITK读图VTK显示

ITK 实现图像数据的读取&#xff0c;然后通过连接器把ITK读取的图像数据传输到VTK 然后进行显示。 #include "itkImage.h" #include "itkImageFileReader.h" #include "itkImageToVTKImageFilter.h" #include "itkJPEGImageIOFactory.h&qu…

python如何读二进制文件_python怎么读二进制文件

实际项目中经常遇到读取二进制问题&#xff0c;Python下读取二进制文件一般用Python的文件打开读写相关函数和struct. python学习网&#xff0c;大量的免费python视频教程&#xff0c;欢迎在线学习&#xff01; 1。获取文件名filename&#xff0c;可用对话框,也可以直接手写 2。…