Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/403.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的最终变量操作_Java_Variables_Final - Fatal编程技术网

Java中的最终变量操作

Java中的最终变量操作,java,variables,final,Java,Variables,Final,有谁能告诉我以下这行在Java环境中的含义是什么 最后一个变量仍然可以是 除非它是不可变的 据我所知,通过将任何变量声明为final,您不能再次更改它,那么上面一行中单词immutable的含义是什么?如果您对Java对象有最终引用,您仍然可以操作它,但不能更改它的引用。例如,此代码完全合法: import javax.swing.JLabel; class Test1 { private final static JLabel l = new JLabel("Old text");

有谁能告诉我以下这行在Java环境中的含义是什么

最后一个变量仍然可以是 除非它是不可变的


据我所知,通过将任何变量声明为final,您不能再次更改它,那么上面一行中单词immutable的含义是什么?

如果您对Java对象有最终引用,您仍然可以操作它,但不能更改它的引用。例如,此代码完全合法:

import javax.swing.JLabel;

class Test1 {
    private final static JLabel l = new JLabel("Old text");
    public static void main(String[] args) {
        System.err.println(l.getText());
        l.setText("New Text");
        System.err.println(l.getText());
    }
}
但你不能说:

l = new JLabel("Newest Text");
在第一次分配到l。请注意,您可以执行以下操作:

import javax.swing.JLabel;

class Test1 {
    public static void main(String[] args) {
        final JLabel l;
        String s = getArbitaryString(); // Assume this method returns a string
        l = new JLabel(s);
        System.err.println(l.getText());
    }
}
这是可以做到的,因为当l被声明时,它并没有被赋值给任何非空的东西。所以你只能给它分配一次

原语也是如此。可以按如下方式为其指定值:

class Test1 {
    public static void main(String[] args) {
        final int i;
        i = 2;
    }
}

但是现在您无法进一步操作它,因为您可以对基元类型执行的唯一操作就是为它们赋值。

您仍然可以使用反射更改“final”变量。

这意味着,如果您的最终变量是引用类型(即不是像int一样的基元),那么它只是不能更改的引用。不能使它引用其他对象,但是如果类允许,它引用的对象的字段仍然可以更改。例如:

final StringBuffer s = new StringBuffer();
StringBuffer的内容仍然可以任意更改:

s.append("something");
但你不能说:

s = null;

另一方面:

final String s = "";

字符串是不可变的-根本没有任何方法可以让您更改字符串(除非您使用反射-见鬼去吧)。

正如其他人所说,这意味着您可以操作变量指向的对象,但您不能更改引用(即为变量指定另一个对象)


可通过设计更改的对象,如
列表
,可以更改(您可以向其添加元素),而如果您有一个不可变的对象,如
字符串
整数
,则无法更改它(类
字符串
支持的所有操作都返回一个新实例,并且不修改实际对象)。

不能更改最终变量引用的对象或值。只能分配一次最终变量


这对您是否可以更改对象的状态没有影响。除非以禁止此操作的方式对对象本身进行编码,否则仍然可以对其进行操作。不可变对象是状态无法更改的对象。

您可以对其调用任何方法,即使该方法可以更改引用对象的状态指的是

final MyClass myClass = new MyClass();
myClass.setVar(something);

这很好,因为
myClass
本身没有改变,也就是说,你没有做总是让我丧命的
myClass=myClass1;


如果您希望最终变量实际上像您认为的那样安全,则需要大量额外的代码来返回字符串[]的副本。

您可以为StringBuffer类型等操作可变的最终变量,但无法操作不可变类型的最终变量。


如果是可变变量,则不会在每次更改其值时都创建新对象。但是如果是不可变类型,则无论何时更改值,都会创建新对象,因此当您将其设置为最终值时,您无法对其进行修改。

是,可以修改最终变量

    final StringBuffer s = new StringBuffer();
    // won't work
    s = new StringBuffer();
    //this works
    s.append("hai");

您不能更改引用,但可以修改对象的字段。

以下是我几年前创建的代码,用于关闭final,然后再打开,以便您可以修改引用/值,它只对变量有效,但确实有效

您也可以对方法句柄执行类似的操作,但是,除非您正在编写某种形式的自动对象解析器/生成器,否则我将避免像瘟疫一样执行这两种操作

public static void setValueOnField(Object instance, Field field, Object value)
        throws NoSuchFieldException, IOException, IllegalArgumentException,
        IllegalAccessException {
    try (Accessor<Field> access = open(field)) {
        field.set(instance, value);
    }
}


  public static class Accessor<T extends AccessibleObject & Member>
            implements Closeable {
        private final boolean isAccessible;
        private final boolean isFinal;
        private final int modifiers;
        private final T accessibleObject;

        private Accessor(T accessibleObject) throws IOException {
            super();
            if (accessibleObject == null) {
                throw new IOException(
                        "Error preparing field for accesibility: Field is null");
            }
            try {
                this.accessibleObject = accessibleObject;
                this.modifiers = accessibleObject.getModifiers();
                this.isAccessible = accessibleObject.isAccessible();
                this.isFinal = Modifier.isFinal(modifiers);
                if (!this.isAccessible) {
                    accessibleObject.setAccessible(true);
                }
                if (this.isFinal) {
                    getModifiersField(accessibleObject).setInt(
                            accessibleObject, modifiers & ~Modifier.FINAL);
                }
            } catch (Exception e) {
                throw new IOException("Error preparing field for accesibility",
                        e);
            }

        }

        @Override
        public void close() throws IOException {

            if (!this.isAccessible) {
                accessibleObject.setAccessible(false);
            }
            if (this.isFinal) {
                try {
                    getModifiersField(accessibleObject).setInt(
                            accessibleObject, modifiers);
                } catch (Exception e) {
                    throw new IOException("Error setting field to final", e);
                }
            }
        }

        public T getAccessibleObject() {
            return accessibleObject;
        }

        private static Field getModifiersField(AccessibleObject toFetch) {
            Field field;
            try {
                field = toFetch.getClass().getField("modifiers");
                field.setAccessible(true);
                return field;
            } catch (Exception e) {
                throw new RuntimeException(
                        "Error occured getting modifiers field", e);
            }
        }
    }
publicstaticvoidsetvalueonfield(对象实例、字段、对象值)
抛出NoSuchFieldException、IOException、IllegalArgumentException、,
非法访问例外{
try(访问器访问=打开(字段)){
field.set(实例、值);
}
}
公共静态类访问器
可关闭的机具{
私有最终布尔值是可访问的;
私有final布尔值是final;
私有final int修饰符;
私有最终可访问对象;
私有访问器(T accessibleObject)引发IOException{
超级();
if(accessibleObject==null){
抛出新IOException(
“为可访问性准备字段时出错:字段为空”);
}
试一试{
this.accessibleObject=accessibleObject;
this.modifiers=accessibleObject.getModifiers();
this.isAccessible=accessibleObject.isAccessible();
this.isFinal=修饰符.isFinal(修饰符);
如果(!this.isAccessible){
accessibleObject.setAccessible(true);
}
如果(此.isFinal){
getModifiersField(accessibleObject).setInt(
accessibleObject、修饰符&~Modifier.FINAL);
}
}捕获(例外e){
抛出新IOException(“准备可访问性字段时出错”,
e) );
}
}
@凌驾
public void close()引发IOException{
如果(!this.isAccessible){
accessibleObject.setAccessible(false);
}
如果(此.isFinal){
试一试{
getModifiersField(accessibleObject).setInt(
可访问对象、修改器);
}捕获(例外e){
抛出新IOException(“将字段设置为最终错误”,e);
}
}
}
公共T getAccessibleObject(){
返回可访问对象;
}
专用静态场
public static void setValueOnField(Object instance, Field field, Object value)
        throws NoSuchFieldException, IOException, IllegalArgumentException,
        IllegalAccessException {
    try (Accessor<Field> access = open(field)) {
        field.set(instance, value);
    }
}


  public static class Accessor<T extends AccessibleObject & Member>
            implements Closeable {
        private final boolean isAccessible;
        private final boolean isFinal;
        private final int modifiers;
        private final T accessibleObject;

        private Accessor(T accessibleObject) throws IOException {
            super();
            if (accessibleObject == null) {
                throw new IOException(
                        "Error preparing field for accesibility: Field is null");
            }
            try {
                this.accessibleObject = accessibleObject;
                this.modifiers = accessibleObject.getModifiers();
                this.isAccessible = accessibleObject.isAccessible();
                this.isFinal = Modifier.isFinal(modifiers);
                if (!this.isAccessible) {
                    accessibleObject.setAccessible(true);
                }
                if (this.isFinal) {
                    getModifiersField(accessibleObject).setInt(
                            accessibleObject, modifiers & ~Modifier.FINAL);
                }
            } catch (Exception e) {
                throw new IOException("Error preparing field for accesibility",
                        e);
            }

        }

        @Override
        public void close() throws IOException {

            if (!this.isAccessible) {
                accessibleObject.setAccessible(false);
            }
            if (this.isFinal) {
                try {
                    getModifiersField(accessibleObject).setInt(
                            accessibleObject, modifiers);
                } catch (Exception e) {
                    throw new IOException("Error setting field to final", e);
                }
            }
        }

        public T getAccessibleObject() {
            return accessibleObject;
        }

        private static Field getModifiersField(AccessibleObject toFetch) {
            Field field;
            try {
                field = toFetch.getClass().getField("modifiers");
                field.setAccessible(true);
                return field;
            } catch (Exception e) {
                throw new RuntimeException(
                        "Error occured getting modifiers field", e);
            }
        }
    }