0

我有一个 Circle 类类型的对象,我有一个成员 'r' 来存储它的半径。现在因为我经常使用这些对象,我不想将半径设为私有,因为其他类必须使用 getR() 方法,这会使代码难以阅读。例如,阅读这样的代码要容易得多: double alpha = b1.r + b2.r -2*b1.r*b2.r; 比读这个:double alpha = b1.getR() + b2.getR() - 2*b1.getR()*b2.getR();

然而,因为这是一个半径,它的平方也被大量使用,我想计算一次,我希望有一个半径的设置器,所以我可以同时更新 r 和它的平方。所以我希望 r 是私有的以强制使用 setR() 但我希望它是 publc 以便它可以被引用以供阅读。有谁知道在 Java 中执行此操作的方法?

4

4 回答 4

4

Java 没有只读属性的概念。

如果您允许 r 可读,则有人可以并且会随机更改它。此外,养成这样的坏习惯。只是不要。长镜头的例子是:如果你需要它在一些奇怪的非欧几里得空间中运行怎么办?现在你必须去解决这个烂摊子。

现实的选择:

您可以偏离规范并将您的 getter 命名为 r()。几乎一样短。

或者,您可以将此类数学推入 circle 类,它可以直接引用其成员。您可以使用较短的名称获得更好的封装部分。

class Circle() {
   static double alpha(Circle c1, Circle c2) {
      return c1.r + c2.r -2*c1.r*c2.r
   }
   ...
}
于 2013-03-10T05:33:27.313 回答
1

一个)。不要跳过使用 getter 和 setter 来封装你的代码。

乙)。如果可读性是您的问题,那么我建议使用 getR() 方法获取半径并存储在局部变量中。例如 - int firstCircleRadius = first.getR() 和其他圆圈类似,并使用您的局部变量使公式易于阅读。

C)。不要使用 r 作为属性名称。改用半径,它本身会增加可读性。

于 2013-03-10T05:35:41.820 回答
0

我个人会使用 getter 和 setter。但是,您可以将真实半径存储在私有成员中,然后使用您setR()的方法更新虚拟半径r。这并不能解决能够r手动更改的问题。

private int radius;
public int r;
public void setR(int r) {
    radius = r;
    square(); //do you squaring and other math
    this.r = r;
}
于 2013-03-10T05:30:46.847 回答
0

我最近一直被这个问题所困扰,并且冒着获得一堆反对票和 Java 社区愤怒的风险,我建议不要依赖 Java 访问 - 类变量或方法(或我曾经认为“私有”是为了封装在面向对象的编程语言中。只需将 public 用于所有内容并在晚上睡个好觉。这是一个解释,请考虑以下课程:

package hiddenscope;

public class Privacy {
    private int privateInt = 12;
    private double oneBy2pi = 0.5 / Math.PI;
    private String myClassName;

    public Privacy () { 
        privateInt = 12;
        myClassName = this.getClass().getName();
        print ("Constructor");
    }

    // Given the circumference of a circle, get its radius
    public double c2r (double c) {
        return c * oneBy2pi;
    }

    // Do not let any other class call this method
    private void print (String caller) {
        System.out.println ("["+caller+"] Current value of privateInt in class " + 
                                                myClassName + " is " + privateInt);
    }
}

这是一个更改上述类的私有变量 privateInt 并将其称为私有“打印”方法的类,甚至从包外部(受保护,有人吗?):

package userpackage;
import hiddenscope.Privacy;

import java.lang.reflect.*;


public class EditPrivate {

    private int i2set;
    private String fieldNameToModify, myClassName;
    private Object p;
    private Method printer;

    public EditPrivate (Object object, String fName, int value) {
        fieldNameToModify = fName;
        i2set = value;
        p = object;
        myClassName = this.getClass().getName();
        Method[] methods = p.getClass().getDeclaredMethods();
        for (Method m : methods) {
            if (m.getName().equals("print")) {
                printer = m;
                printer.setAccessible(true);
                break;
        }}

        if (printer == null)
            return;

        try {
            printer.invoke (p, myClassName);
        } catch (IllegalAccessException ex1)        {   ex1.printStackTrace();
        } catch (InvocationTargetException ex2)     {   ex2.printStackTrace();
    }}

    public void invadePrivacy () throws Exception {
        Field[] fields = p.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            if (fieldName.equals(fieldNameToModify)) {
                field.setAccessible(true);
                if ("int".equals(field.getType().toString())) {
                    try {
                        field.setInt(p, i2set);
                        if (printer != null)
                            printer.invoke (p, myClassName);
                        return;
                    } catch (IllegalAccessException ex) {
                        ex.printStackTrace();
        }}}}
        throw new Exception ("No such int field: " + fieldNameToModify);
    }

    public static void main(String[] args) {
        try {
            Privacy p = new Privacy();
            new EditPrivate(p, "privateInt", 15).invadePrivacy();
        } catch (Exception ex) {
            ex.printStackTrace();
}}}

为了增加对这种伤害的侮辱,这就是多个线程将类的内部变量和私有变量弄乱时发生的情况(oneBy2pi 应该是私有的!)

package userpackage;
import java.lang.reflect.Field;
import java.util.concurrent.*;
import java.util.*;

import hiddenscope.*;

public class ThreadedPi implements Runnable {

    Privacy p = new Privacy();
    private int nSample = 2000, bins[] = new int[4]; // 94814117 999065 0003379, 2028859
    private Field c2dField;
    private boolean mutate;

    public ThreadedPi () {
        Field[] fields = p.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            if (fieldName.equals("oneBy2pi")) {
                field.setAccessible(true);
                c2dField = field;
    }}}

    synchronized private boolean setMutationOfField (boolean master, boolean value) {
        if (master)
            mutate = value;
        return mutate;
    }

    public void run () {
        Random rng = new Random();
        for ( ; ; ) {
            if (setMutationOfField (false, true)) {
                int nDigit = 2 + rng.nextInt(4);
                double doublePi = 4.0 * Math.atan(1.0),
                        decimal = Math.pow(10, nDigit),
                        apprxPi = Math.round(decimal * doublePi) / decimal;
                try {
                    c2dField.setDouble (p, 0.5/apprxPi);
                } catch (IllegalAccessException ex) {
                    ex.printStackTrace();
            }} else {
                return;
    }}}

    public void execute () {
        setMutationOfField (true, true);
        new Thread (this).start();
        Executed[] class2x = new Executed[nSample];
        ExecutorService executor = Executors.newCachedThreadPool();
        for (int i = 0 ; i < 4 ; i++)
            bins[i] = 0;
        for (int i = 0 ; i < nSample ; i++) {
            class2x[i] = new Executed();
            executor.execute(class2x[i]);
            double d = class2x[i].getDiameter(-1);
            if (d < 399.99)         bins[0]++;
            else if (d < 400)       bins[1]++;
            else if (d < 400.01)    bins[2]++;
            else                    bins[3]++;
            //System.out.println ("d: " + d);
        }
        setMutationOfField (true, false);
        for (int i = 0 ; i < 4 ; i++)
            System.out.print("\t\t[" + (i+1) + "] " + bins[i]);
        System.out.println ();
    }

    public static void main(String[] args) {
        ThreadedPi tp = new ThreadedPi();
        for (int k = 0 ; k < 5 ; k++)
            tp.execute();
    }

    private class Executed implements Runnable {
        private double d=-1, c = 2513.274123;

        synchronized double getDiameter (double setter) {
            if (setter < 0) {
                while (d < 0) {
                    try {
                        wait();
                    } catch (InterruptedException ex) {
            }}} else {
                d = setter;
                notify();
            }
            return d;
        }

        public void run () {
            getDiameter (p.c2d(c));
}}}

上面所有的类都能完美地编译和运行,这就解释了为什么“private”在java中可能没有任何意义。盾牌起来,斯科蒂!

于 2013-03-10T06:09:24.200 回答