Java对于一个完全的初学者来说似乎在创建新对象时显得多余。

huangapple go评论128阅读模式
英文:

Java seems redundant for a complete beginner when creates new objects

问题

对不起,如果这个问题看起来很愚蠢,我是一个完全的初学者,Java 构造新对象的方式对我来说似乎多余。以矩形包为例:

import java.awt.Rectangle

Rectangle box = new Rectangle(5, 10, 20, 30);

那么为什么我们要两次写 Rectangle 呢?仅仅写成:

box = new Rectangle(5, 10, 20, 30);

不够吗?以这种方式编写,清楚地表示我的对象将从 Rectangle 构造函数创建。

英文:

I'm sorry if this question seems stupid, I'm a complete beginner and the way Java constructs new objects seems redundant for me. Using the rectangle package for example:

import java.awt.Rectangle

Rectangle box = new Rectangle(5,10,20,30)

So why do we write Rectangle twice? just writing

box = new Rectangle(5,10,20,30)

isn't enough? writing this way it's clear that my object will be created from the Rectangle constructor

答案1

得分: 9

不总是多余的将变量的类型和实例化的对象的类都指定出来。

这两者可能是不同的。

例如,与你的示例不同,你可以这样写:

Shape box = new Rectangle(5,10,20,30);

这允许你按照接口(Shape)来编程,而不是特定的实现(Rectangle)。

如果你希望变量的类型与你实例化的类相同,你可以在 Java 10 中使用 var

var box = new Rectangle(5,10,20,30);

除此之外,在声明新变量时,你必须告诉编译器。

如果你只写了:

box = new Rectangle(5,10,20,30);

编译器会期望 box 变量已经在该语句的作用域内被声明过。加上变量的类型(或 var)可以让编译器知道这是一个新变量。

英文:

It's not always redundant to specify both the type of the variable and the class of the object that you instantiate.

The two may be different.

For example, instead of your example, you can write

Shape box = new Rectangle(5,10,20,30);

which allows you to program to the interface (Shape) instead of a specific implementation (Rectangle).

If you want the type of the variable to be the same as the class you instantiate, you can use var as of Java 10:

var box = new Rectangle(5,10,20,30);

Other than that, you have to tell the compiler when you are declaring a new variable.

If you just write

box = new Rectangle(5,10,20,30);

the compiler expects the box variable to already be declared somewhere within the scope of that statement. Adding the type of the variable (or var) lets the compiler know this is a new variable.

答案2

得分: 3

写两者的原因是语义上的差异。

如果只写 box = ...,那么你是在给一个已经存在的变量或字段 box 赋值。但是在赋值之前,它必须在该作用域中存在!

如果你写的是 Rectangle box = ...,相反地,你在该作用域中定义了一个新的变量,并为其赋值。

不能写 Rectangle box = (5, 10, 20, 30); 的原因在于,可能有许多不同的类符合类 Rectangle。这是因为 Java 类的固有特性是可扩展的(有一堆例外情况)。这意味着变量(Rectangle)的类型并不总是与实际对象的类型完全相同。

英文:

The reason you need to write both is a semantic difference.

If you only write box = ..., then you assign a value to a preexisting variable or field called box. But it has to exist in that scope before the assignment!

If you write Rectangle box = ... instead, you define a new variable at that scope and assign it a value.

The reason you can't write Rectangle box = (5, 10, 20, 30); is, that there can potentially be many different Classes that conform to the class Rectangle. The reason is the inherent character of classes in Java, that they are extendible (with a bunch of exceptions). This means that the type of the variable (Rectangle) does not always have to be the very same as the type of the actual object.

答案3

得分: 1

我认为在这里需要传达的重要概念是对象变量之间的区别。

    Rectangle box = new Rectangle(5,10,20,30)

右边的部分,'new Rectangle...' 创建了一个对象,并返回对该对象的引用

左边的部分,'Rectangle box',声明了一个变量,该变量能够保存对矩形(或任何其他从矩形派生的对象,但不在本课程中讨论)的引用。

这些内容可以分开处理:您可以创建对象,而不必立即将值保存在新声明的变量中;举个假设的例子,也许您想要

    draw(new Rectangle(5,10,20,30));

创建一个矩形,以某种方式显示它,然后您不再需要引用该矩形。同样,您可以声明一个变量,而不必立即将其初始化为任何值。

    Rectangle box;

当然,在这种情况下,您最终需要为变量赋值,以使其有用,但不必在声明时就赋值。

最后,如其他答案中所提到的,

   Rectangle box = …

   box = …

是完全不同的。第一个声明了一个新变量,第二个使用了现有变量。如果我们将第二种情况视为隐式声明,那么您可能会遇到输入错误:也许您输成了'b0x'而不是'box',这时'box'的值就不会得到预期。出于这个原因,大多数但不是所有的编程语言都要求明确声明变量。

是的,Java 有点冗长。

英文:

I think the important concept to get across here is the distinction between object and variable.

In

    Rectangle box = new Rectangle(5,10,20,30)

the right-hand side, 'new Rectangle...' creates an object, and returns a reference to that object.

The left-hand side, 'Rectangle box', declares a variable that is capable of holding a reference to a Rectangle (or to any other object subclassed from Rectangle, but that's not in this lesson).

These things can stand separately: you can create objects without immediately saving the value in a newly-declared variable; for a hypothetical example, maybe you'd want

    draw(new Rectangle(5,10,20,30));

to create a rectangle, display it somehow, and then you don't need to refer to the rectangle ever again. And likewise you can declare a variable without immediately initializing it to anything.

    Rectangle box;

Of course in this case you'll eventually need to assign a value to box for it to be useful, but it doesn't have to be done on declaration.

And lastly, as mentioned in other answers,

   Rectangle box = …

and

   box = …

are quite different. The first declares a new variable, the second uses an existing variable. If we made the second case an implicit declaration, then you're vulnerable to typing errors: maybe you typed 'b0x' instead of 'box', and now you have a bug in that 'box' did not get the expected value. For this reason, most but not all programming languages require explicit declaration of variables.

And yes, Java is somewhat wordy.

答案4

得分: 0

一种形式的语句

Foo f = new Bar(....);

说明了两件事。首先,它表明变量 f 的类型是 Foo。在右侧,你正在创建一个类型为 Bar 的对象。如果 FooBar 的超类型,那么这是允许的。在Java中,变量和对象都有类型。

英文:

A statement of the form

Foo f = new Bar(....);

says two things. First, it says the type of the variable f is Foo. On the right-hand side, you are saying that you are creating an object of type Bar. This is allowed if Foo is a supertype of Bar. Both variables and objects in Java have type.

答案5

得分: 0

在Java中,类和变量的定义是显式的。此外,请注意您可以使用不同的接口实现或使用子类。例如,您可以定义一个接口,它不能独立使用 - 例如 java.util.List。根据实现,它将在底层执行不同的代码,并且可以在以后进行替换(例如 ArrayList vs. LinkedList)。

在您的示例中,您有一个 Rectangle - 这是一个子类,也实现了接口。因此,所有这些都将是有效的赋值:

Shape        box1 = new Rectangle(5,10,20,30);
Serializable box2 = new Rectangle(5,10,20,30);
Cloneable    box3 = new Rectangle(5,10,20,30);

这使得将来的开发人员更容易理解您针对哪些接口进行了开发,从而使您能够以后替换矩形。

确实,与一些新语言相比,存在一些冗余,但是您提到的非冗长语法也有其缺点。定义和赋值具有相同的语法。因此,如果您想创建一个已经存在的变量 'box',您正在将一个值赋给预先存在的变量。在显式表示中,您会创建名称冲突并获得编译器错误:

无编译器错误:

Rectangle box; // 对于一些像JS这样的语言,不需要这个
...
box = new Rectangle(5,10,20,30);
box = new Rectangle(6,11,21,31);

编译器错误:

Rectangle box = new Rectangle(5,10,20,30);
Rectangle box = new Rectangle(6,11,21,31);

在方法接口中也可能面临相同的问题。特别是如果这不是您的代码,一些糟糕的开发人员在编码和文档方面做得很差:

Python:

def my_function(name):
    print(name)

Java:

public static void myFunction(String name){
    System.out.print(name);
}

(请注意,Python也支持类型,但您不必强制使用)。

人们会争论更少的代码将导致更多的可见性和更干净的代码,但是在许多企业级项目中工作后,我会随时选择显式的冗余,而不是含糊和双重功能的语法。

英文:

Definition of classes and variables are explicit in Java. Also note you can use different implementation of interfaces and or use subclasses. For example you can define an interface which cannot be used stand alone - e.g. java.util.List. Depending in the implementation it'll execute different code under the hood and is replaceable later on (ArrayList vs. LinkedList for example).

In your example you have Rectangle - which is a subclass and also implements interfaces. So all of this would be valid assignments:

Shape        box1 = new Rectangle(5,10,20,30);
Serializable box2 = new Rectangle(5,10,20,30);
Cloneable    box3 = new Rectangle(5,10,20,30);

This makes it easier for future devs to understand which interfaces you developed against, enabling you to replace rectangle later on.

Indeed there's some redundancy compared to some newer languages, but not the non-verbose syntax you suggested has it's downsides by it's own. Definition and assignment have the same syntax. So if you want to create a variable 'box' that is already existing you're assigning a value to the pre-existing variable. In the explicit notiation you create a name clash and get a compiler error:

No compiler error:

Rectangle box; // This is not needed for some languages like JS
...
box = new Rectangle(5,10,20,30);
box = new Rectangle(6,11,21,31);

Compiler error:

Rectangle box = new Rectangle(5,10,20,30);
Rectangle box = new Rectangle(6,11,21,31);

Same problem can be faced with method interfaces. Especially it it's not your code and some poor devs did a bad job in coding and documenting:

Python:

def my_function(name):
    print(name)

Java:

public static void myFunction(String name){
    System.out.print(name);
}

(Please note python supports typing as well, but you are not forced to).

People will argue less code will lead to more visibility and cleaner code, but having worked in many enterprise scale projects I'd pick explicit redundancy over slink and double-functional syntax any time.

huangapple
  • 本文由 发表于 2020年10月27日 18:48:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/64552807.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定