【发布时间】:2015-06-26 17:46:50
【问题描述】:
访问 java 类的方法的最佳方式是什么?
- 创建对象 - 如果我们每次都创建对象,那么它会消耗大量内存。
- 如果创建对象的成本很高,那么为什么我们不总是使用静态方法来访问 java 类的资源呢?
提前致谢!!
【问题讨论】:
标签: java object static-methods
访问 java 类的方法的最佳方式是什么?
提前致谢!!
【问题讨论】:
标签: java object static-methods
这完全取决于方法的行为是应该针对类的一个实例,还是针对每个可能的实例。
我们并不总是使用静态,因为有时我们希望对象做出不同的反应。 假设我们有一个 Person 类,有两个“实例”,你和我。 如果我们要实现一个方法:
public static String getName(){ ....
}
我们中的一个人将不得不改变他的名字。为此,您希望每个 Person 实例都有不同的回复,因此这里不适合使用静态。
在这里,您需要两个实例,一个实例变量名称(由构造函数或 mutator 设置)对我来说会返回“Hans”,对你来说会返回“Pushpendra”
【讨论】:
一个静态方法属于该类 并且非静态方法属于 一个类的对象。这是一个 只能调用非静态方法 在一个类的对象上 属于。静态方法可以 但是在课堂上都被称为 以及类的对象。一种 静态方法只能访问静态 成员。非静态方法可以 访问静态和非静态 成员因为当时 调用静态方法,类 可能不会被实例化(如果是 调用类本身)。在里面 其他情况下,非静态方法可以 仅在类有时调用 已经实例化了。一个静态的 方法由所有实例共享 班级。
我有来自here的数据。
【讨论】:
最好的方法!!?
没有任何最好的方法。根据您的目的,所有方法都是有用的和好的。
方法static 的决定不仅仅取决于对象的创建和它的开销,你还需要考虑可用性。
如果一个方法可以为所有实例共享并且不需要依赖于任何对象属性,那么您可以很高兴地将其设为静态。
它还需要考虑你将如何使用它。记住静态方法或字段不属于对象,它属于类
【讨论】:
对于使用静态的类的所有实例,您希望行为应该保持不变,这是一种节省内存的好习惯。
如果您希望每个类实例更改方法行为,请使用非静态方法。
假设您有一个构建客户订单的程序。
返回任何订单的标准包装成本的方法应该是静态的。不依赖于类属性的方法应该是静态的。
而根据所选菜单返回订单成本的方法应该是非静态的。
还有太多的静态方法会增加类加载时间。
静态方法不能被覆盖,所以你不能利用多态的力量。通常静态方法用作实用程序类,如Math.double() Math.float()
【讨论】:
对象确实更昂贵,但出于维护原因,它通常是值得的: 您的类封装了传递给静态方法会很乏味的数据。例如。如果“登录”方法需要从 MySQL 数据库和 Mongo 中查找用户数据 - 那么将数据库连接传递给每个调用是很乏味的:
public class LoginService{
public static login(String user,String password, DataSource mySQLConnections, MongoClient mongoClient) ...
这个签名很难阅读,更糟糕的是:它对多态不灵活。如果我们曾经将用户数据从 mySQL+mongo 迁移到 LDAP,那么我们需要修复对“login(user,password,LDAPClient)”的每个调用
现在,您可能仍然认为这可以静态解决:
public class LoginService{
private static DataSource mySQLConnections;
private static MongoClient mongoClient;
public static login(String user,String password) ...
// and if we ever migrate to LDAP, we just change the internal statics, without affecting the public signature:
public class LoginService{
private static LDDAPClient;
public static login(String user,String password) ...
有时这已经足够了,但许多程序员仍然觉得它有局限性。有关详细信息,请阅读 Spring 和“依赖注入”,但底线是 - 我可能想使用 LoginService,有几个实例(一个使用 LDAP,另一个使用 MySQL+Mongo),并根据一些管理切换它们命令,甚至只是为了测试。这归结为具有不同实现类的接口,每个类都封装了其所需的帮助器:
public interface LoginService{
public login(String user,String password) ...
}
public class LoginServiceDb implements LoginService{
private DataSource mySqlConnections;
private MongoClient mongoClient;
public login(String user,String password)
// use the databases
...
}
public class LoginServiceLDAP implements LoginService{
private LDAPClient ldap;
public login(String user,String password)
// use LDAP
...
}
另请注意: 对垃圾收集的影响可能不会那么糟糕(取决于您的需求以及您的“实时”程度)。一些对象可能会被缓存和重用。一些对象的使用非常短暂,以至于它们仍然处于 GC 处理得相当好的“婴儿”一代
【讨论】: