在Java中,创建对象';s的成员是否公开?

在Java中,创建对象';s的成员是否公开?,java,field,private,encapsulation,public,Java,Field,Private,Encapsulation,Public,我的应用程序中有一个数据类。我的应用程序永远不会被用作公共API,我将是唯一一个在我的项目中开发代码的人 我正在尽可能节省每一盎司的处理器和内存 让我的数据类中的数据成员具有public/protected/default保护,这样我就不必使用getter,这是个坏主意吗?使用getter需要稍微多一些内存和创建堆栈之类的东西,我认为这是不必要的。我能看到使用getter的唯一原因是为了保护/隐私,但是如果我是唯一的程序员,没有其他人会使用我的API,那么不使用getter是个坏主意吗 请让我知

我的应用程序中有一个数据类。我的应用程序永远不会被用作公共API,我将是唯一一个在我的项目中开发代码的人

我正在尽可能节省每一盎司的处理器和内存

让我的数据类中的数据成员具有public/protected/default保护,这样我就不必使用getter,这是个坏主意吗?使用getter需要稍微多一些内存和创建堆栈之类的东西,我认为这是不必要的。我能看到使用getter的唯一原因是为了保护/隐私,但是如果我是唯一的程序员,没有其他人会使用我的API,那么不使用getter是个坏主意吗


请让我知道这是否愚蠢。

这有点异端,但我同意你的观点,如果你知道没有其他人会使用你的课程,你可以跳过这些内容。我不会在可能被重用的代码中这样做,即使隐藏在API后面,但在您的情况下,它似乎相当安全。

我很确定所使用的内存量可以忽略不计。如果您是为生产构建的,JVM甚至可能会根据运行时的实现优化调用,使其内联。如果您自己开发它,它可能仍然会有帮助,因为如果您有一个难以跟踪的bug,您可以在getter/setter中设置一个断点,并准确地看到您何时更改值。也不应该编写任何代码,因为大多数现代IDE都具有自动生成代码的功能

这并不愚蠢,但我认为这也可能不是个好主意

我理解这种诱惑…如果没有其他人在使用代码,那么你就不必担心它。但一次又一次,结果证明这与实际发生的情况不符……你发现你将在比你想象的更多的地方使用它,或者项目变得比预期的更大,或者有人只是得到了它,认为它是有用的…事情从来没有打算永久或公开有一种方式成为这种方式


真的有那么严格的处理器功率和内存限制吗?我不知道你的情况(也许是嵌入式应用?),但作为一个(过度概括的)规则,你最好去别处寻找资源……在你的数据结构、算法、,或者架构,以更好地改善内存或CPU。

很可能琐碎的getter和setter将被内联,但对于公共字段,您将失去契约(API)和实现之间的区别。即使这只是一个您将要使用的API,在IMO中保持松散耦合也是很好的。

Python人员不使用getter,他们不会在地狱中燃烧

Getter/setter是一种将类的一部分公开给Java的简单内省的方法。JavaBean规范依赖公共getter和setter来确定哪些属性是重要的

虽然对于需要/产生/使用bean的事物来说是必不可少的,但它不是OO编程或Java编程的基本特性。它只是Bean规范的一部分,对于任何想要参与类似Bean的事情的类来说都是必需的


公共属性很好。它们简单、直接、显而易见

任何堆栈的使用都是高度暂时的,无论如何都不是确定的。您可能会发现编译器优化了任何不必要的开销,因此您可能会发现实际上什么也得不到


我同意私有的非API类使用公共成员并不一定是坏事,但你所获得的收益是如此之小(如果有的话),我就不想麻烦了。

你永远不知道,总是像读你代码的人知道你住在哪里一样编写代码,并且是连环杀手。即使您只为自己开发代码,也要尝试(imo)像在团队中开发一样进行开发。这样,您就习惯于构建可读的最佳实践代码。至于性能开销,如果你真的需要你的每一位内存和CPU的每一个周期,那么最好用C这样的语言来实现。

从谁编写代码和谁将使用代码的角度来看,那么不管是你还是其他人,您可能仍然需要getter和setter——如果以后有人使用它作为事实上的公共API的话

然而,如果它真的只是数据,并且您不需要任何与类相关的行为,那么一定要让成员公开

对我来说,真正重要的是类是否有任何行为,或者您是否希望更改其数据成员的名称或类型作为实现细节


关于处理器功率和内存-您测量了吗?

如果您要更换getter/setter以优化性能/内存,那么您采取的方法是错误的。这些几乎肯定不是应用程序运行缓慢或占用太多内存的原因

优化的主要罪过是在你知道你需要做之前就去做。只有当你有真实的信息显示你在哪里浪费了最多的时间/内存时才进行优化,然后花时间进行优化。这背后的想法是,在一段占总运行时间80%的代码中减少5%的时间,比在一段只占总运行时间5%的代码中减少20%的时间,可以获得更多的收益。(这同样适用于内存)


另外,我会按照您的建议小心地设计应用程序,因为这意味着一些属性(例如:简单属性)可以直接访问,而其他属性(更复杂的派生属性,或者您不想公开底层类型的属性)将具有getter/setter。因此,您最终将使用混合的访问样式,这将减少可维护性。

与任何优化一样,在优化之前和之后进行测量,看看是否有任何好处可以证明 public class Point { public final int x; public final int y; public Point(final int xVal, final int yVal) { x = xVal; y = yVal; } }
public class DataClass {
    public int a;
    public String b;
    public char c;
}
private bool visible = true;

public bool Visible
{
    get
    {
        return visible && Parent.Visible;
    }
    set
    {
        visible = value;
    }
}
WithGS  Without
1.1323  1.1116

Diff  = 0.0207 secs.
PersonGetSet.java


public class PersonGetSet {
    private String name;
    private boolean deceased;

    public void setName( String name ) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public void setDeceased( boolean deceased ) {
        this.deceased = deceased;
    }
    public boolean isDeceased() {
        return this.deceased;
    }

    public static void main( String [] args )  {
        PersonGetSet pb = new PersonGetSet();
        pb.setName( "name" );
        pb.setDeceased( true ) ;

        long start = System.currentTimeMillis();
        PersonGetSet [] array = new PersonGetSet[2000000];
        for( int i = 0 ; i < array.length; i++ ) {
            PersonGetSet personGs = new PersonGetSet();
            personGs.setName( pb.getName() );
            personGs.setDeceased( pb.isDeceased() );
            array[i] =  personGs;
        }
        System.out.println( "PersonGetSet took " + ( System.currentTimeMillis() - start ) + " ms. " );
    }
}


Person.java


public class Person {
    String name;
    boolean deceased;
    public static void main( String [] args )  {
        Person pb = new Person();
        pb.name=  "name" ;
        pb.deceased = true;

        long start = System.currentTimeMillis();
        Person [] array = new Person[2000000];
        for( int i = 0 ; i < array.length; i++ ) {
            Person simplePerson = new Person();
            simplePerson.name=  pb.name;
            simplePerson.deceased = pb.deceased;
            array[i] =  simplePerson;
        }
        System.out.println( "Person took " + ( System.currentTimeMillis() - start ) + " ms. " );
    }
}
double ret = myObj.calculateReturn()
int v = myObj.getValue();
int ov = myObj.getOldValue();
double ret = (v-ov)/ov * 100; // do I work about dividing by zero etc.?