【问题标题】:Use of Static Methods静态方法的使用
【发布时间】:2011-10-09 10:42:58
【问题描述】:

我正在编写一个简单的接口类,如下所示。我只需要将其中一种方法提供给用户。使用这个类的用户只需要这个特定方法的返回值(checkLink)。因此,我单独将此方法声明为受保护的,因此它仅对调用Iface 类的用户可见。由于类中的其余方法将在类中使用,因此它们被声明为私有。我添加了静态关键字,因为这些方法有点“无状态”。我对类变量使用了 static final 关键字,因为我想要像 #define 这样的 C 语言。

由于我是 C 程序员,我对 Java 世界还是陌生的。请看一下我的代码框架,并告诉我所做的声明是否正确传达了含义。

package com.prog.Test;
import java.net.*;
import java.io.*;

public class Iface{   

    private static final int MSG_OK     =   0x01;
    private static final int MSG_NOK    =   0x00;   
    private static final int MSG_FAIL   =   0xFF;    

    private static byte[] getBytesFromUrl(URL link) throws IOException {
        ......                  
        return bytes;
    }               

    private static int[] msg_header(byte[] msg) throws Exception
    {
        int len = msg.length;
        System.out.println("len ="+len);
        int[] headerMsg =new int [3]; 
        headerMsg[0]= MSG_OK; 
            ......

        return headerMsg;
    }

    private static byte[] Tobyte(int[]src) {
            ....
    }

    protected static int checkLink (URL url ) throws IOException {

       byte[] rbuffer = null;
       byte[] hdr = null;
       int status = -1; 

        try{             
            rbuffer = getBytesFromUrl(url);
            ..
            ..
            hdr = Tobyte(msg_header(rbuffer));
            ...
            ...
            status = 0; 

        }catch (Exception e) {
            System.err.println("Exception:  " + e);
        }
        return status; 

  }
}

所以当我在应用程序中使用这个Iface 类时,我这样称呼它:

public class Trial {  

    public static void main (String [] args ) throws IOException {

        URL url = new URL("http://localhost:8000/myfile");

        System.out.println("Calling Iface");

        int retval = Iface.checkLink(url);      

        System.out.println("retval ="+retval);
    }
}

我也试过这个(在删除checkLink() 方法中的static 关键字之后):

 public class Trial {  

        public static void main (String [] args ) throws IOException {

            URL url = new URL("http://localhost:8000/myfile");

            System.out.println("Calling Iface");

                Iface callInterface;

            int retval = callInterface.checkLink(url);      

            System.out.println("retval ="+retval);
        }
    }

有区别吗?

【问题讨论】:

  • 有错误吗?还是这只是代码审查?
  • 我以为我偶然发现了书评

标签: java methods static


【解决方案1】:

通过实例和类调用静态方法在 Java 中的功能是等效的。以下:

Iface.checkLink(<url>);

在功能上等同于

Iface foo = new Iface();  // or Iface foo;   but with the caveats below
foo.checkLink(<url>);

但是,请注意,后者不推荐,因为它令人困惑且不必要。可以说是因为a mistake by the Java language designers才被允许。

警告:在您的示例中,您没有初始化 Iface 变量。你仍然可以通过这个变量调用静态方法,但是如果你将它用于静态方法以外的任何东西(你一开始不应该这样做!),你可能会遇到问题。

事实上,您可能应该去make this class uninstantiable,因为它似乎是一个只有静态方法的实用程序类。

【讨论】:

  • 我同意“你不应该这样做”。我忘了在我的回答中提到这一点。
  • 所以学习是我应该让我的类本身不可实例化。或者,如果我不这样做,至少如上所述初始化它。但是还是建议通过类调用静态方法。
  • @user489152 是的,确切地说,对于专门用于存放静态方法的类,您应该遵循"Java static class?" 中的步骤。是的肯定只通过类调用静态方法。
  • @Daniel DiPaolo:当然,如果由于 StriplingWarrior 在他的回答中提到的原因,我必须从 checkLink 方法中删除该静态关键字,那么我将像您的后一种方法一样实例化该类
  • @user489152 是的,当然,您也希望使其不可实例化
【解决方案2】:

从技术上讲,您发布的代码示例都不应该工作。

protected 关键字告诉 Java 仅允许扩展 Iface 类的类访问该变量。您没有在调用代码中扩展该类,因此如果该方法不是 public,则使用该方法的任何方法都不应编译。

请注意,创建static 方法意味着调用者将需要直接使用Iface 类,从而无法使用类继承。因此,如果您想要拥有另一个扩展 Iface 并覆盖 checkLinks 的实现的类,您需要使该方法成为非静态方法。

如果方法是非静态的,你会想这样使用它:

Iface callInterface = new Iface();
int retval = callInterface.checkLink(url);   

您可能还想对工厂模式和依赖注入模式进行一些研究,这使您可以更灵活地确定要使用哪个特定的Iface 实现。

【讨论】:

  • :“受保护”表示只有同一个包中的子类和类可以访问它。因此,当我在同一个包中的应用程序中使用 Iface 类时,它应该可以正常工作吗?因为我刚刚测试了我的代码并且它可以工作..
  • @user49152:确实如此。我曾假设调用代码在不同的包中。 protected 关键字最适合在您期望某人扩展您的课程时使用。否则,如果您不指定任何访问关键字,则默认访问级别将允许同一包中的其他类访问该方法,同时阻止该方法在其他包中的子类使用它。见download.oracle.com/javase/tutorial/java/javaOO/…
【解决方案3】:

是的, 通过这样做:Iface callInterface; 您正在创建 Iface 类的实例,因此在内存中保留了一些空间。 但是,您仍在执行静态方法,因此您不能使用任何实例方法/属性。

所以在执行方面,不​​会有任何区别。在内存/垃圾回收方面,会有。

【讨论】:

  • 在你创建并引用一个对象之前,它不是一个对象的实例......它只是那个类型的一个变量。
  • 哦,是的,你是对的。他没有调用构造函数。这不是在堆栈而不是堆中创建它吗?
  • 由于变量从未设置为任何值,JIT 无疑会优化它。不会为变量保留堆栈空间。
  • @StriplingWarrior:那么既然我没有为Iface调用构造函数,那它就不会有堆栈空间了?
  • @user489152:由于您没有callInterface 变量分配任何内容,因此不会分配堆栈空间。由于您没有调用构造函数,因此不会分配堆空间。
【解决方案4】:

当然有区别。

静态方法不是对象的成员,它们属于类。

所以如果checkLink() 是静态的,那么你应该从类本身调用它:IFace.checkLink()

从对对象的引用中调用它会起作用,但从逻辑上讲,这不是正确的含义。因为方法不属于对象,不会作用于对象的实际状态。

【讨论】:

    【解决方案5】:

    我猜你的问题会更准确,比如“静态是什么意思?”。

    对我来说,简单的“静态”意味着这些变量每个类只存在一次,所有其他变量都在来自该类的每个对象中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      • 2012-06-17
      • 2014-06-27
      相关资源
      最近更新 更多