构造函数(Java)

发布于 2024-08-15 03:21:27 字数 330 浏览 9 评论 0原文

我想知道当我在类级别定义变量而不是使用构造函数时,这是否是一个大错误(在小型 Java 类程序中)?我们可以这样做吗?

两种情况下方法体都是相同的。

非常感谢!

例如。

public class test{

    static int column1 = 0;
    static int column2 = 1;

    public static void main(String[] args){
    // do something with variables, no return
    }

    /...../

}

I wonder if it's a big error (in small one class Java program) when I define variable in a class level rather that using the constructor? Can we do that?

The method body will be the same in both cases.

Many thanks!

eg.

public class test{

    static int column1 = 0;
    static int column2 = 1;

    public static void main(String[] args){
    // do something with variables, no return
    }

    /...../

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

年少掌心 2024-08-22 03:21:28

作为风格注释,如果您正在谈论实例变量以及应该在哪里初始化它们 - 如果在构造函数中或在声明中,我通常更喜欢在构造函数中仅初始化传递给构造函数的内容(或者依赖于这些参数的内容) ),并在声明中初始化不存在的内容。我认为这样更干净。

As a style note, if you're talking about instance variables and where you should initialize those - if in the constructor or in the declaration, I usually prefer initializing in the constructor only what's passed to the constructor (or that are dependent of those parameters), and initializing in the declaration what is not. I think it's cleaner that way.

ゞ花落谁相伴 2024-08-22 03:21:28

我假设您的问题本质上是在类变量的声明中或在构造函数中分配默认/初始值是否更合适。如果是这样的话,正如大多数回复所指出的那样,这主要归结为风格偏好。

根据我的经验,我发现在类级别声明中分配默认值通常会使代码更具可读性,并使类构造函数的管理更易于管理。 (即,如果您的类作为多个构造函数,则不必a)担心在多个位置设置值,或者b)担心创建必须的通用初始化方法从每个构造函数调用)。

在构造函数中设置类变量的默认/初始值确实没有什么坏处,并且对于小型单构造函数类,两种选择的优点或多或少是相等的。但是,如果您预计该类可能会随着时间的推移而增长,我会发现在声明中分配值将使该类的增强变得更容易一些。

I'm assuming your question is essentially whether it is more proper to assign a default/initial value at the class variable's declaration or in a constructor. If that's the case, as most of the responses have indicated, it mostly boils down to a style preference.

In my experience, I've found that assigning a default value at the class-level declaration makes the code generally more readable and makes the management of the class's constructors a little more manageable. (i.e. you don't have to a) worry about setting the value in multiple places if your class as multiple constructors or b) worry about creating a generic initialization method that must be called from each constructor).

There is really no harm in setting the default/initial value of a class variable in the constructor and for small single-constructor classes, the merits of either choice are more or less equal. However if your anticipate the class may grow over time, I would find assigning the value at the declaration would make enhancement of the class a little easier.

べ繥欢鉨o。 2024-08-22 03:21:28

一个只有 main() 方法的一次性小程序?为什么不呢。

但更好的方法是将其放在 main 中

public class test{
  public static void main(String[] args){
    int column1 = 0;
    int column2 = 1;
    // do something with variables, no return
  }
}

an one-off little program of only main() method? why not.

but a better way is to put it inside main

public class test{
  public static void main(String[] args){
    int column1 = 0;
    int column2 = 1;
    // do something with variables, no return
  }
}
半衾梦 2024-08-22 03:21:27

你的意思

public class Foo {
    private String test = "Hello";
    ...
}

public class Foo {
    private String test;

    public Foo() {
        test = "Hello";
    }
}

我实际上更喜欢第一种方法,它更干净。如果您提前知道该值并且它是一个常量,则应该按照您的定义设置该值。从技术角度来看,没有理由不这样做,而且它看起来更干净。

更新

鉴于您添加的代码示例,您所做的一切都很好。需要考虑的一件事是您的常量应该是final。在您的情况下,它们可能应该是private static final int

You mean

public class Foo {
    private String test = "Hello";
    ...
}

instead of

public class Foo {
    private String test;

    public Foo() {
        test = "Hello";
    }
}

I actually prefer the first method, it is much cleaner. If you know the value ahead of time and it's a constant, you should set the value as you define it. No reason not to from a technical standpoint, and it looks much cleaner.

Update

Given the code sample you add, what you're doing is fine. One thing to consider is that your constants should be final. In your case they should likely be private static final int.

血之狂魔 2024-08-22 03:21:27

这没有什么区别。

It doesn't make any difference.

假装爱人 2024-08-22 03:21:27

实际上,

如果这些属性应该有一个默认值,并且您的类有多个构造函数,那么在“类级别”启动这些变量可能是一个好主意,因为您可能会忘记设置其中一些变量的值。

当然,您可以创建一个方法来启动这些变量,但即使如此,您也可能忘记从某些构造函数中调用此方法。

所以,从这个意义上说,这可以被认为是一个很好的做法。

Actually,

if these attributes should have a default value, and your class have more than one constructor, may be a good idea do initiate these variables in "class level", since you may forget to set value of some of these variables.

Of course, you could create a method to start these varibles, but even so, you could forget to call this method from some of your constructors.

So, in this sense, this could be considered a good practice.

再可℃爱ぅ一点好了 2024-08-22 03:21:27

如果你的意思是(如 jcm 所说):

public class Foo {
    private String test = "Hello";
    ...
}

而不是(此处进行小编辑):

public class Foo {
    private String test;

    public Foo() {
        this.test = "Hello";
    }
}

如果它是一个常数,则将其设为常数。如果不是,那么它的值取决于运行时序列,我会选择第二个,而不是第一个。我不喜欢在声明时初始化,这意味着我必须在太多地方查找值。作为风格问题(这在很大程度上是风格,而不是实质),我更喜欢声明声明并分配赋值,而不是混合两者。常数是另一回事。

但在小型一类应用程序中,它并不那么重要。

编辑:考虑到您更新的代码示例(使用类字段而不是实例字段),我可能根本不会这样做。 (这个问题不再有意义;构造函数与静态字段无关。)FWIW,我通常会在声明时初始化静态字段,因为其他任何事情都非常不常见,即使有一些称为“静态”的东西当顺序很重要时,您可以使用初始化器:

static int foo;
static int bar;

// Static initializer
static {
    foo = 7;
    bar = foo + 1;
}

但根据我的经验,它们的使用非常罕见,最不令人惊讶的事情就是在声明时初始化静态变量。

If you mean (as jcm said):

public class Foo {
    private String test = "Hello";
    ...
}

instead of (small edit here):

public class Foo {
    private String test;

    public Foo() {
        this.test = "Hello";
    }
}

If it's a constant, then make it a constant. If it isn't, then its value is dependent on the runtime sequence, and I'd plump for the second of those, not the first. I'm not a fan of initializing at declaration-time, it means I have to look at too many places for values. As a matter of style (and this is style, not substance, for the most part), I prefer to declare declarations and assign assignments, not inter-mix the two. Constants are a different thing.

But in a small one-class application, it's not like it matters much.

Edit: Allowing for your updated code example, which uses class fields rather than instance fields, I probably wouldn't do that at all. (And the question kind of doesn't make sense any more; constructors have nothing to do with static fields.) FWIW, I would generally initialize static fields at declaration time because anything else is very uncommon, even though there are things called "static initializers" you can use when order is important:

static int foo;
static int bar;

// Static initializer
static {
    foo = 7;
    bar = foo + 1;
}

But in my experience, their use is rare enough that the least surprising thing is just to initialize the statics at declaration time.

笑梦风尘 2024-08-22 03:21:27

你的意思是做这样的事情吗?

public class MyClass
{
    private int _someInt = 13;
    private String _someString = "I'm a string.";
}

如果这就是你的意思,我认为这样做没有什么问题,它相当于在构造函数中初始化它。

Do you mean doing something like this?

public class MyClass
{
    private int _someInt = 13;
    private String _someString = "I'm a string.";
}

If that's what you mean, I see nothing wrong with doing that, it's equivalent to initializing it in the constructor.

弥繁 2024-08-22 03:21:27

根据您的编辑,看起来您确实询问是否可以使用静态变量。 (我注意到@TJ,你的示例程序中根本没有构造函数!)

我对此的回答是:

  • 一般来说,静态变量是糟糕的风格和糟糕的主意.

  • 在由单个类组成的小型应用程序中,它不会有太大区别...除非您稍后决定在更大的应用程序中重用该类。

另一方面,静态常量的风格也不错。例如,

static final int COLUMN_1 = 0;
static final int COLUMN_2 = 1;

重写您的示例以消除静态变量将如下所示:

public class Test2 {

    private int column1 = 0;
    private int column2 = 1;

    public static void main(String[] args) {
        new Test2.run(args);
    }

    private void run(String[] args) {
        /* do something with the variables */
    }

    /* ... */
}

与原始版本相比,它的优点是您现在可以在其他上下文中安全地重用 Test2 类。例如,这将起作用:

for (int i = 1; i < 10; i++) {
    // call "new Test2().run(args)" in a new thread
}

由于静态耦合,这可能会出现错误:

for (int i = 1; i < 10; i++) {
    // call "test.main(args)" in a new thread
}

Based on your edits, looks like you are really asking about whether it is OK to use static variables. (I note with @T.J. that you don't have a constructor at all in your example program!)

My answer to that is:

  • In general, static variables are bad style and a bad idea.

  • In a small application consisting of a single class, it won't make much difference ... unless you later decide to reuse the class in something larger.

On the other hand, static constants are not bad style; e.g.

static final int COLUMN_1 = 0;
static final int COLUMN_2 = 1;

A rewrite of your example that eliminates the static variables would look something like this:

public class Test2 {

    private int column1 = 0;
    private int column2 = 1;

    public static void main(String[] args) {
        new Test2.run(args);
    }

    private void run(String[] args) {
        /* do something with the variables */
    }

    /* ... */
}

The advantage of this over the original version is that you can now safely reuse the Test2 class in other contexts. For example this will work:

for (int i = 1; i < 10; i++) {
    // call "new Test2().run(args)" in a new thread
}

where this is likely to be buggy due to static coupling:

for (int i = 1; i < 10; i++) {
    // call "test.main(args)" in a new thread
}
深爱不及久伴 2024-08-22 03:21:27

其他评论中有一些关于变量范围的好建议。我还有一个相关的评论。我经常注意到,由于从 main(String arg) 方法开始,开发人员对实例/静态变量感到困惑。由于此方法是静态的,因此人们往往不会费心创建实例,最终只会得到静态方法和字段。对于一小段测试代码来说这不是问题,但是一旦您需要多个类和面向对象的设计,它很快就会变得很麻烦。

避免这种情况的一个有用方法是不从 main 方法开始,而是从单元测试开始:

import junit.framework.Assert;
import junit.framework.TestCase;

public class MyAppTest extends TestCase {

    public void testCreateMessage() {

        MyApp myApp = new MyApp("Always write a Te");            
        String message= myApp.createMessage("stackoverflow");   
        assertEquals("Always write a Test", message); 
    }
}

记住将测试放在单独的源目录中,即应用程序代码的 src/test/java 与 src/main/java 。这使得单独运行和部署应用程序代码变得更容易,并遵循 Maven 2 默认布局。

那么你的类可能看起来像这样(稍微修改以适应我的解释):

public class MyApp {

    // constants always like this
    private static final int COLUMN_ONE = 0;
    private static final int COLUMN_TWO = 1;

    // make instance variables final if possible
    private final String name;

    public MyApp(String name) {
        this.name = name;
    }

    public void String createMessage(String arg) {
        return name + arg.charAt(COLUMN_ONE) + arg.charAt(COLUMN_TWO);            
    }    
}

现在只需运行你的单元测试。在 Eclipse 中,右键单击类 MyAppTest 并选择“作为 JUnit 测试运行”。通过这种方式,您将从面向对象的正确方向开始。

如果您稍后想让您的应用程序可执行,您可以向 MyApp 添加一个 main 方法,或者创建一个小的引导类来完成这项工作:

public class MyAppStarter {

    public static void main(String[] args) {

        MyApp myApp = new MyApp(args[0]);
        System.out.println(myApp.createMessage("!!"));
    }
}

这个解决方案的好处是您可以保留命令行参数和其他操作的解析启动应用程序的详细信息与业务代码分开。

There's some good advice in other comments about scoping of variables. I have another related remark. I often notice developers getting confused with instance/static variables due to starting off with the main(String arg) method. Because this method is static, one tends to not bother with creating an instance, and ends up with only static methods and fields. This is no problem for a tiny piece of test code, but as soon as you need multiple classes and an Object-Oriented design, it becomes a nuisance very quickly.

A useful way to avoid this would be to not start off with the main method, but with a unit test:

import junit.framework.Assert;
import junit.framework.TestCase;

public class MyAppTest extends TestCase {

    public void testCreateMessage() {

        MyApp myApp = new MyApp("Always write a Te");            
        String message= myApp.createMessage("stackoverflow");   
        assertEquals("Always write a Test", message); 
    }
}

Remember to put tests in a separate source directory, i.e. src/test/java vs src/main/java for your application code. This makes it easier to run and deploy your application code separately and follows the Maven 2 default layout.

Then your class could look like this (slightly modified to suit my explanation):

public class MyApp {

    // constants always like this
    private static final int COLUMN_ONE = 0;
    private static final int COLUMN_TWO = 1;

    // make instance variables final if possible
    private final String name;

    public MyApp(String name) {
        this.name = name;
    }

    public void String createMessage(String arg) {
        return name + arg.charAt(COLUMN_ONE) + arg.charAt(COLUMN_TWO);            
    }    
}

Now just run your unit test. In Eclipse, right-click on the class MyAppTest and choose "Run as JUnit test". In this way you will start off on the right Object-Oriented foot.

If you later want to make your application executable, you can either add a main method to MyApp, or create a small bootstrap class to do the work:

public class MyAppStarter {

    public static void main(String[] args) {

        MyApp myApp = new MyApp(args[0]);
        System.out.println(myApp.createMessage("!!"));
    }
}

The nice thing of this solution is that you can keep the parsing of commandline arguments and other operational details of starting your application separated from the business code.

梦幻的心爱 2024-08-22 03:21:27

这是我在 Java 中处理变量的方法:

  1. 除非证明一切都是最终的
    但事实并非如此。
  2. 当它是时什么都没有初始化
    除非必须声明(仅
    switch 中使用的已经完成
    不同的是)
  3. 每个变量的范围都很小
    (这包括可见性)作为
    可能

假设您有以下情况:

public class Foo 
{
    // constants must always be immutable (no changeable state)
    public static final String EXTERNAL_CONSTANT;
    private static final String INTERNAL_CONSTANT;

    public static final int EXTERNAL_CONSTANT_USED_IN_SWITCH = 1;
    private static final int INTERNAL_CONSTANT_USED_IN_SWITCH = 2; 

     // no public variables that can be modified
     private static int internalClassVariable;

     static
     {
         EXTERNAL_CONSTANT = "Hello";
         INTERNAL_CONSTANT = "World";
     }

     private final List<String> constantsMustBeStaticAndFinal;
     private int instanceVariable;

     {
         constantsMustBeStaticAndFinal = new ArrayList<String>();
     }

     public Foo(final int parametersAreAlwaysFinal)
     {
         final int localVariable;

         locatlVariable   = parameterAreALwaysFinal * 10;
         instanceVariable = localVariable;
     } 
}

总结一下:

  • 常量始终为 UPPER_CASE
  • 类变量始终为混合大小写
  • 常量始终在 a 中初始化
    静态块,除非它们用于
    开关(编译器要求)
  • 类变量始终
    在静态块中初始化的
  • 实例变量总是
    大小写混合的
  • 实例变量,其值为
    编译时已知已初始化
    在实例块
  • 实例变量中,其值为
    编译时未知的是
    在构造函数中初始化

具有以下优点:

  • 可以从文件中读取值(例如
    属性文件),因为
    初始化发生在静态中
    矿石
  • 实例块你可以做什么
    像打开文件这样的事情,
  • 因为它们大多是最终的
    编译器会让你知道当你
    忘记初始化它们,
  • 因为它们大多是最终的
    拥有不可变性的更好机会
    类是一种更安全的编码方式,
  • 您有一些定义明确的地方可以
    寻找变量的来源
  • 您可以更轻松地更改的
    变量初始化稍后没有
    搞砸了

对于那个丢失的点,请考虑以下代码:

{
    int x = 0;    

    // this line added later
    x = 7;
}

为什么将 x 设置为 0,然后设置为 7,而不使用 0(这是一个简单的情况,有些在运行时更昂贵)。如果x被标记为final,那么将其更改为7的人会意识到他们必须摆脱将其设置为毫无意义的0。

自从大约1993年开始专业使用C/C++(对于Java)以来,我一直以这种方式进行编程自 1995 年以来),它对我很有帮助。

Here is how I do variables in Java:

  1. everything is final unless it proves
    that it cannot be.
  2. nothing is initialized when it is
    declared unless it has to be (only
    those used in switch are done
    differently)
  3. every variable has as small a scope
    (this includes visibility) as
    possible

Given that you have the following cases:

public class Foo 
{
    // constants must always be immutable (no changeable state)
    public static final String EXTERNAL_CONSTANT;
    private static final String INTERNAL_CONSTANT;

    public static final int EXTERNAL_CONSTANT_USED_IN_SWITCH = 1;
    private static final int INTERNAL_CONSTANT_USED_IN_SWITCH = 2; 

     // no public variables that can be modified
     private static int internalClassVariable;

     static
     {
         EXTERNAL_CONSTANT = "Hello";
         INTERNAL_CONSTANT = "World";
     }

     private final List<String> constantsMustBeStaticAndFinal;
     private int instanceVariable;

     {
         constantsMustBeStaticAndFinal = new ArrayList<String>();
     }

     public Foo(final int parametersAreAlwaysFinal)
     {
         final int localVariable;

         locatlVariable   = parameterAreALwaysFinal * 10;
         instanceVariable = localVariable;
     } 
}

To summarize:

  • constants are always UPPER_CASE
  • class variables are always mixedCase
  • constants are always initialized in a
    static block unless they are used in
    a switch (compiler requirement)
  • class variables are always
    initialized in a static block
  • instance variables are always
    mixedCase
  • instance variables where the value is
    known at compile time are initialized
    in an instance block
  • instance variables where the value is
    not known at compile time are
    initialized in the constructors

The has the benefits of:

  • can read values from a file (say
    properties file) since the
    initialization happens in the static
    ore
  • instance block where you can do
    things like open the file
  • since they are mostly final the
    compiler will let you know when you
    forget to initialize them
  • since they are mostly final you have
    a better chance of having immutable
    classes which is a safer way to code
  • you have a few well defined places to
    look for where variables get their
    values
  • you can more easily make changes to
    variable initialization later without
    screwing it up

For that lost point, consider the following code:

{
    int x = 0;    

    // this line added later
    x = 7;
}

Why set x to 0 and then to 7 without ever using the 0 (this is a simple case, some are more expensive at runtime). If x was marked as final the person changing it to 7 would realize that they have to get rid of setting it to the pointless 0.

I have been programming in this sort of way since using C/C++ professionally starting in about 1993 (for Java since 1995), and it has served me well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文