0

我需要找到一种通过getter函数直接修改Java中类的私有成员的方法。我知道我可以使用这样的指针在 C++ 中做到这一点;

class FooBar
{
    private:
        Foo foo;

    public:
        Foo* getFoo()
        {
            return &foo;
        }
}

foo然后我可以通过公共函数直接操作私有变量,getFoo()因为 getFoo() 返回一个指针(例如。getFoo()->callFunction();

所以我想知道的是,有没有办法在Java中复制这种完全相同的效果??....有什么办法吗?

4

7 回答 7

5
class FooBar {
    private Foo foo;

    public Foo getFoo() {
        return foo;
    }
}

Java 中的所有对象变量都是对对象的引用,因此您可以将它们视为“锁定”指针。“锁定”的意思是你不能用它做任何指针算术。

于 2012-12-23T09:23:19.587 回答
2

因为,Java 没有Pointer. 但是,你可以这样做,使用gettersetter,它会帮助你喜欢这样

class myclass{
private myclass val;  // private field

//get the private field
public myclass getVal(){
return val;
}

//set/change the member field value
public void setVal(myclass val){
this.val=val;
}

}
于 2012-12-23T09:19:16.327 回答
2

在 java 中,您的 getter 返回对对象的引用,因此您可以依靠返回对象的公共方法来修改它。如果您详细说明您想要做什么,我可以进一步详细说明。举个例子,

如果 getter 返回一个列表,则调用者可以使用 add 或 remove 方法修改列表。

于 2012-12-23T09:20:05.657 回答
1

您必须提供一个 getter 和一个 setter

class FooBar {

    private Foo foo;

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

}
于 2012-12-23T09:32:09.683 回答
1

您需要什么可以通过简单的 getter 访问,如已经显示的那样。一些重要的细节:

如果你想像

getFoo()->callFunction();

确保:

  • Foo类是可见的(如果您在同一个包中,则默认修饰符,如果调用者是子类或public则受保护
  • callFunction() 是可见的(相同的规则)

如果你想像

getFoo().value = newValue;

确保 value 是可修改的,这意味着 Foo 类没有将 value 定义为 final:

class Foo {
    // in this case value is immutable
    final Bar value;
}

在最后一种情况下,编译器会告诉您“无法分配最终字段 Foo.value”。

于 2012-12-23T10:44:14.077 回答
0

Java 是按值传递,或者更具体地说,按值传递引用。这意味着所有引用类型都被传递,这样:

List<String> a = myObj.getList();
a.add("My String"); // this modifies the source list

List<String> b = new ArrayList<String>();
a = b; // this doesn't change the source list's reference

在使用 Java 编程时,大多数人尝试尽可能实现最高级别的封装,将可变类型转换为不可变类型(例如使用复制构造函数习语)。这是在 OOP 空间中编程的好方法。

如果你没有 setter,你可能想使用 Java 的内置反射:

public class Test {
    private String NAME = "OLD NAME";

    public String getName() {
        return this.NAME;
    }

    public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Test t = new Test();
        System.out.println(t.getName()); // OLD NAME

        Field f = t.getClass().getDeclaredField("NAME");
        f.setAccessible(true); // allows access to private field 
        f.set(t, "NEW NAME");

        System.out.println(t.getName()); // NEW NAME
    }
}

但请注意,反射是一个高级主题,在大多数情况下是糟糕编程的症状。

于 2012-12-23T09:48:26.270 回答
0

即使在 C++ 中,这也是一个坏主意,因为如果对象被释放,您的指针现在将指向无效的内存位置。这是您在 Java 中没有指针的原因之一;为了保护要从流氓指针访问的内存。因此,在 Java 中,对私有字段的所有访问都必须通过封闭对象本身进行,通常使用 get/set 组合。

但是,我认为使用 set() 不是您想要的解决方案;可能是因为您有来自不同类的对象集合,这些对象不共享除 Object 之外的公共层次结构。如果是这种情况,那么一个潜在的解决方案是创建和使用一个通用接口。这样,您可以使用这个通用接口来存储这些不同对象的引用并以相同的通用方式操作它们;例如:

static void test() {

    List<IntegerGetSet> list = new ArrayList<IntegerGetSet>();
    list.add (new A1(1));
    list.add (new B1(2));

    for (IntegerGetSet igs: list) {
        igs.set (igs.get() * 10);               
        System.out.println(igs.get()); 
    }
}

interface IntegerGetSet {   
    public int get();
    public void set (int i);
}

static class A1 implements IntegerGetSet {

    private int i;

    public A1 (int i) { this.i = i; }

    @Override
    public int get() {
        return i;
    }

    @Override
    public void set(int i) {
        this.i = i;
    }       
}

static class B1 implements IntegerGetSet {
    private int i;

    public B1 (int i) { this.i = i; }

    @Override
    public int get() {
        return i;
    }

    @Override
    public void set(int i) {
        this.i = i;
    }       
}

如果你不能修改这些类,那么你将有一些更复杂的东西来做;例如,通过使用另一篇文章中建议的反射。

于 2012-12-23T10:54:58.830 回答