【问题标题】:Why is Eclipse suggesting I make my method static为什么 Eclipse 建议我将方法设为静态
【发布时间】:2013-11-17 17:50:52
【问题描述】:

我正在从一个类中调用一个方法,它给了我一个错误以使该方法成为静态。我很困惑为什么,因为我问了这个问题What's the difference between a class variable and a parameter in a constructor?,我的理解是类变量是静态的。

患者类别:

public  String  setOption(String option) throws IOException
{
        option = stdin.readLine();
        //stuff here
    return option;
}

患者管理系统:

public class PatientManagementSystem
{
    static BufferedReader stdin = new BufferedReader(new InputStreamReader(
            System.in));
    public static void main(String[] args) throws IOException
    {
        Patient.setOption(null);    
    }
}

错误:

我是将方法更改为静态还是创建局部变量?

【问题讨论】:

  • 将方法更改为static 的建议是错误的:它基于假设您的调用是正确的,但事实并非如此。
  • 请注意,调用setOption 而不对其返回值做任何事情根本没有效果。
  • 很难在没有看到您的患者课程的情况下判断。可能你有一些属性,比如option。那么setOption 应该将该选项设置为作为参数传递的值。从标准输入读取不应该在 setter 中完成。
  • 与其描述你的错误,不如告诉我们你到底想要达到什么目的。
  • 哪个 IDE 提出了这个建议?

标签: java eclipse methods static-methods


【解决方案1】:

根据您之前的问题,我认为可能没有完全挖掘局部变量的概念。在这种方法中:

public String setOption(String option) throws IOException
{
    option = stdin.readLine();
    return option;
}

option 是一个局部变量。每次调用该变量时,您都会将该变量的 初始值 作为参数传递给 setOption 方法(并且您碰巧忽略了该值),但是不影响该细节,这是一样

public String setOption() throws Exception
{
    String option = stdin.readLine();
    return option;
}

现在,局部变量与实例或类变量完全不同:它们仅在方法体内有效,并且仅在方法执行期间存在。考虑到这一点,让我们看一下这段代码:

static BufferedReader stdin = new BufferedReader(new InputStreamReader(
        System.in));
public static void main(String[] args) throws IOException
{
    Patient.setOption(null);    
}

在这里,您基本上是在将类变量 stdin 误用为应该是局部变量的东西:

public static void main(String[] args) throws IOException
{
    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
    Patient.setOption(null);    
}

关于你的方法调用的问题...setOption 当前是一个instance 方法,这意味着它必须在实例的上下文中调用。您按原样调用它,不涉及 Patient 的实例。如果你继续沿着这条路走下去,你将不能代表一个以上的病人,可能不是你的想法。所以你想保持方法不变并创建一个Patient的实例:

Patient p = new Patient();
p.setOption(...);

在您的整体设计中,尚不清楚setOption 应该扮演什么角色,但它使用静态stdin 变量并不是一个好主意(我已经在上面将其设为本地)。您希望将从stdin 读取的任何数据传递给setOption 方法,从而将其与输入读取逻辑解耦。

【讨论】:

  • 你想让用户说“我想调用 setOption”吗?这绝对不应该在setOption 内决定,而是在main 内决定,它应该读取和解释用户输入并调用适当的方法。
【解决方案2】:

您(可能)需要创建Patient 类的对象。

Patient myPatient = new Patient();
myPatient.setOption(null);

使用如此有限的信息很难确定您想做什么。我不知道你打算对 Patient 类做什么,但我最好的猜测是什么?这样做是有意义的,因为您尝试使用 setter 命名约定调用方法。

如果您不打算实例化一个对象,而是走将setOption 设为static 方法的路线,那么您可能应该更改方法名称。


通过更深入地解释您到底想要完成什么(甚至不谈论伪代码,只是对您想要做什么的一个非常抽象的想法),更容易解释更多关于static 此处(带有您的具体示例)以及您应该做什么等。

【讨论】:

  • @Skippy-psI'mawoman 然后你需要做的就是调用你的构造函数(无论是默认的还是其他的),就像我在实例化对象的回答中所做的那样。然后在该实例化对象上调用setOption(null)
【解决方案3】:

我是将方法更改为静态还是创建局部变量?

两者都可以。

如果您的方法不使用类变量,最好将其设为静态,这样您就不必为方法调用实例化类。

【讨论】:

    【解决方案4】:

    何时制作静态与非静态的问题取决于正在建模的真实世界对象/概念。让我们以这段代码中的Patient 对象为例。在没有看到任何关于Patient 的代码的情况下,仍然很清楚Patient 是什么 以及它代表什么。所以,最简单的:

    • 如果您使用特定 Patient(比如说Jane Doe)做某事,那么它就不是静态的。它在Patient实例上运行。
    • 如果您正在针对 Patient 的概念做一些事情,那么它就是静态的。

    所以一些非静态操作可能是:

    • 更新Patient 的名称
    • Patient 从医院入院/出院
    • Patient 转移到另一个Doctor

    所有这些都会涉及到一个特定的 Patient,它会在某处被初始化:

    var janeDoe = new Patient("Jane Doe");
    // ...
    janeDoe.TransferTo(doctorSmith);
    

    我实际上很难为Patient 考虑一些静态方法。最常见的静态方法示例可能是工厂方法,您可以在其中获得现有的PatientPatients 的集合。比如:

    var janeDoe = Patient.Fetch("Jane Doe");
    

    或:

    var todaysPatients = Patient.Fetch(DateTime.Today);
    

    各种辅助方法通常也是静态的,例如,可能是 Patient 对象上的一个方法,它接受 MedicalRecord 对象并将其转换为不同的格式。

    但总体思路是一样的。如果您正在与某个对象的特定实例进行交互,那么您需要该对象的一个​​实例来表示该现实世界的概念。

    【讨论】:

    • @Skippy-psI'mawoman:如果没有更多上下文,老实说,听起来这个功能根本不应该成为Patient 对象的一部分。获取用户输入是应用程序关注的问题。 Patient 对象应该只关注Patient 所做的事情,而不包括获取用户输入。一方面,这会将Patient 类与特定的输入/输出场景“紧密耦合”,这不是一件好事。更具体地说,这个方法所做的就是获取输入并返回它。它没有做任何与Patient 相关的事情。
    • @Skippy-psI'mawoman:别担心,面向对象编程像其他任何事情一样需要练习。在这样的事情中(同样,对整个系统了解很少)我可能会创建一个对象,其唯一目的是与用户交互、显示输出和收集输入。然后该对象可以与Patient 对象的实例交互以管理系统的状态。有关我无法提供的更多信息,请查看“S.O.L.I.D.”面向对象设计原则。它们是创建对象的非常有用的指南。
    【解决方案5】:

    因为您直接调用该方法而不创建类对象。

    When to have static methods?

    【讨论】:

      【解决方案6】:

      要以静态方式调用方法,您必须将其设为静态:

      public static String  setOption(String option) throws IOException
      

      但在您的示例中,如果 stdin 不是您的 Patient 类的静态成员,则它无法工作。

      总而言之,您可以按照在声明为静态时调用方法的方式调用方法。在静态方法中,您只能访问类的静态成员。

      【讨论】:

      • @Skippy-psI'mawoman 这就是为什么我试图在我的回答中尽可能完整^^
      【解决方案7】:

      在您的 main method 中试试这个:

      Patient myPatient = new Patient();
      myPatient.setOption(null);
      

      【讨论】:

        【解决方案8】:

        当我们打算将这些方法用作实用方法时,我们会创建具有静态方法的类,例如 Integer 类中的 parseInt。因此要么修改方法

        public static String  setOption(String option) throws IOException // STATIC
        {
            option = stdin.readLine();
            //stuff here
            return option;
        }
        

        然后使用类似的方法

            Patient.setOption(null);    
        

        为 Patient like 实例化一个对象

            Patient obj = new Patient();
            obj.setOption(null);    
        

        【讨论】:

          【解决方案9】:

          在 Java 中 main 方法是特殊的。这是您的代码的起点。可以从代码中的任何位置调用静态方法。因此实际上它不属于包含类。 main 方法也是如此。

          因此,您应该在 main 方法中构造对象,然后使用构造的实例的方法。如果您不构造实例,那么您的 ide 将识别错误并建议您将其设为静态。

          【讨论】:

          • 不。实际上如果 setOption 方法设置了 Patient 类的一个属性,你应该在 Patient 类中编写 setOption 方法。在这个阶段,你只需要坚持不使用除 main 方法之外的静态方法。因为它们就像单独的方法,只需要类来命名。尝试写一切正常。静态值用于不同类中常用的通用方法和属性。
          猜你喜欢
          • 2014-06-26
          • 1970-01-01
          • 2020-02-23
          • 2015-08-04
          • 2010-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-24
          相关资源
          最近更新 更多