【问题标题】:Do I use static methods in Java properly?我是否在 Java 中正确使用静态方法?
【发布时间】:2015-05-22 18:46:00
【问题描述】:

我正在用 Java 创建一个在后台播放音乐的简单游戏。

Music 类包含那些静态方法:

  • playMusic();
  • stopMusic();
  • changeVol(int vol);

一开始我正在创建“Music”类的新对象,并且正在调用静态方法“playMusic”:

    new Music();    
    Music.playMusic();

这些方法之所以是静态的,是因为我想在应用程序启动时开始播放音乐,但是您可以在设置中选择是否播放音乐。静态方法提供了最简单的方法,因为 'Settings' 类没有 'main' 方法。

音乐类代码:

public class Music {
/// ... variables   

public Music(){     
    try{
        /// ... Preparing clip to play
        } catch (Exception e){
            /// ... Catching exception
        }
}

public static void playMusic(){
     /// ... starting music       
}

public static void stopMusic(){
      /// stoping music
}

public static void changeVol(int vol){
    /// changing volume 
}}

它工作得很好,但我想知道它是否符合 OOP 和 Java 标准?

完整音乐课代码:http://pastebin.com/d9XYX1gG

【问题讨论】:

  • 如果不使用对象,为什么还要创建它?这没有意义。
  • 即使没有看到你的方法里面有什么,它看起来也很臭。我认为如果您重新编写逻辑以使用实例方法,它会更清晰。这有什么问题?只需在应用程序启动时创建Music 的实例。
  • 单例更适合您的音乐播放器,因为您可以在需要时保存音乐播放器的状态,而不是拥有丑陋的静态类成员(并且仍然可以全局访问)
  • 有人说使用过多的静态方法违反OOP...
  • 无需创建对象。所有方法都是静态的,您可以像在这里一样通过它们的类名直接调用它们。 Music.playMusic();

标签: java oop methods static


【解决方案1】:

不,这不是使用 OOP 的正确方法。通过使用 static 关键字,您可以使类具有不需要对象且不具有任何数据封装(在实例级别)的方法。

如果你确实想使用静态方法,你可以写Music.playMusic(),但是你的构造函数不会被调用。当您使用静态方法时,您无法访问实例变量,因此您在构造函数中所做的任何准备工作都可能无法被静态方法访问,因为您不能使用 this 关键字。

理想情况下,您应该从每个方法中删除静态,将您想要的任何内容传递给构造函数(如果需要),然后这样调用:

//assume file is a music file
Music music = new Music(file);
music.playMusic();

这将使用传递的音乐文件,假设这是您在构造函数中准备的内容。如果您在整个程序中只有其中一个,您可以使用Singleton Pattern

如果您仍然想走静态路线,并且需要在调用任何静态方法之前一次性准备一些东西,您应该使用所谓的class initializer。要使用它,您将删除您的构造函数,因为您不需要初始化对象,而是用您的类中看起来像这样的方法替换它:

static{
    try{
        /// ... Preparing clip to play
     } catch (Exception e){
        /// ... Catching exception
     }
 }

请记住,类初始化程序保证在您调用类中的任何方法(静态或对象级别)之前运行,但在加载类时运行,不一定在第一次调用静态方法时运行.

【讨论】:

    【解决方案2】:

    你可能想做的是这样的:

    Music music = new Music();
    music.playMusic();
    

    这里不需要静态方法。

    如果您只想要一个可以从多个地方访问的实例,请尝试使用单例:

    public class Music {
    
        private static instance Music instance;
    
        private Music() {
            // initialize your stuff here
        }
    
        // have your instance methods here
    
        /**
          * This is the method to access the Music singleton
          */
        public static Music getInstance() {
            if (instance == null) {
                instance = new Music();
            }
            return instance;
        }
    }
    

    【讨论】:

    • 或者使用静态方法:Music.playMusic();
    • @Radek 这正是 OP 现在正在做的事情。你当然可以有一个静态初始化器,从而摆脱构造函数。
    • @blalasaadri 很好,但是我怎样才能在两个不同的类中访问这个对象呢?
    • @PoQ 最好的解决方案可能是将其作为单例。因此,您有一个私有构造函数和一个静态方法(通常称为 getInstance() 之类的东西),它返回一个静态实例(它在第一次调用时创建)。我在回答中为此添加了一个示例。
    【解决方案3】:

    不,您不需要创建对象来调用静态方法。所以...

    Music.playMusic();
    

    ...无需先创建新实例即可正常工作。

    我也不相信这里真的需要静态。您可以对程序进行初始化,读取设置等,然后创建一个 Music 对象并启动音乐 - 或不启动音乐,具体取决于设置。

    【讨论】:

    • 实例可能被创建,因为构造函数做了一些初始化。当然不理想,如果不需要实例,初始化也可以静态完成。
    • 不错的猜测,但老实说,称“不理想”是一种非常友好的表达方式;-)
    猜你喜欢
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2011-07-30
    相关资源
    最近更新 更多