为什么不是实例变量?
Why not instance variable?
我对 Java 比较陌生(我正在学习 AP 计算机科学),我的书 Big Java 提出了这个问题:
Consider the following implementation of a class Square:
public class Square {
private int sideLength;
private int area; // Not a good idea
public Square(int length) {
sideLength = length; }
public int getArea() {
area = sideLength * sideLength;
return area; }
}
Why is it not a good idea to introduce an instance variable for the
area? Rewrite the class so that area is a local variable.
我确信答案对于更有经验的编码员来说是显而易见的,但我真的不确定为什么将 area 设为实例变量是一种糟糕的方法。任何指导将不胜感激!
我不确定作者的(其他)意思是什么,我想出的一件事是每次实例化时它都会在内存中占用额外和冗余的 space物体。而您可以将简单的方法主体编写为
public int getArea() {
return sideLength * sideLength;
}
这样,您不会在内存中占用任何额外的 space,您将计算发送到 CPU 并获得结果。这在实际应用中是一种很好的方法。对于初学者来说,了解变量的创建、类型匹配等会更容易理解。没有其他的。
面积是根据边长计算的值。实例变量保存对象的状态,如果你将它包含在那里,你将不得不维护两个冗余的状态。
将 area 包含为实例变量将算作 缓存,因为您保存了结果而不是重新计算。这有时是需要的,但在这里不是因为计算足够便宜。
将变量的范围最小化被认为是一种好的做法。
这是因为变量应该只在您知道变量适用且具有有用值的上下文中可用。
这里有两个可能会引入的错误,因为范围比应有的范围更广:
// This function compiles and looks correct, but only works if `getArea()`
// just happened to be called first. Otherwise, it returns 0.
int getVolume(int height) {
return area * height;
}
如果您将 area
的作用域最小化(通过将其设为局部变量),则此代码将无法编译,也就不会出现此错误。
// This functions compiles and looks correct, but will sometimes return
// the area of a single side if another thread is trying to call getArea()
// at the same time, because both will overwrite the same variable.
int getCubeArea() {
area = 6 * sideLength * sideLength;
return area;
}
同样,如果 area
是局部变量,则不会出现此问题。
陈述的其他答案实际上是正确的,因为可以通过知道边长(轻松)计算面积,因此在单独的变量中跟踪它是没有意义的。这就是作者的意思 - 使 area 变量成为其 getter 方法的局部变量 。您可以通过删除字段声明
来做到这一点
private int area;
并在你的方法中局部声明你的变量,所以在你的 getter:
int area = sideLength * sideLength;
return area;
但是,如果您不想每次都重复该计算,那么保留该字段是有意义的
getArea() 被调用。但是,为了做到这一点,您需要从 getter 中取出计算并放入构造函数中。
更新:
跟进 "that_other_guy" 正确答案,如果该区域在构造函数中取值,这些错误都不会发生,一切都会 return 正确结果
我对 Java 比较陌生(我正在学习 AP 计算机科学),我的书 Big Java 提出了这个问题:
Consider the following implementation of a class Square:
public class Square { private int sideLength; private int area; // Not a good idea public Square(int length) { sideLength = length; } public int getArea() { area = sideLength * sideLength; return area; } }
Why is it not a good idea to introduce an instance variable for the area? Rewrite the class so that area is a local variable.
我确信答案对于更有经验的编码员来说是显而易见的,但我真的不确定为什么将 area 设为实例变量是一种糟糕的方法。任何指导将不胜感激!
我不确定作者的(其他)意思是什么,我想出的一件事是每次实例化时它都会在内存中占用额外和冗余的 space物体。而您可以将简单的方法主体编写为
public int getArea() {
return sideLength * sideLength;
}
这样,您不会在内存中占用任何额外的 space,您将计算发送到 CPU 并获得结果。这在实际应用中是一种很好的方法。对于初学者来说,了解变量的创建、类型匹配等会更容易理解。没有其他的。
面积是根据边长计算的值。实例变量保存对象的状态,如果你将它包含在那里,你将不得不维护两个冗余的状态。
将 area 包含为实例变量将算作 缓存,因为您保存了结果而不是重新计算。这有时是需要的,但在这里不是因为计算足够便宜。
将变量的范围最小化被认为是一种好的做法。
这是因为变量应该只在您知道变量适用且具有有用值的上下文中可用。
这里有两个可能会引入的错误,因为范围比应有的范围更广:
// This function compiles and looks correct, but only works if `getArea()`
// just happened to be called first. Otherwise, it returns 0.
int getVolume(int height) {
return area * height;
}
如果您将 area
的作用域最小化(通过将其设为局部变量),则此代码将无法编译,也就不会出现此错误。
// This functions compiles and looks correct, but will sometimes return
// the area of a single side if another thread is trying to call getArea()
// at the same time, because both will overwrite the same variable.
int getCubeArea() {
area = 6 * sideLength * sideLength;
return area;
}
同样,如果 area
是局部变量,则不会出现此问题。
陈述的其他答案实际上是正确的,因为可以通过知道边长(轻松)计算面积,因此在单独的变量中跟踪它是没有意义的。这就是作者的意思 - 使 area 变量成为其 getter 方法的局部变量 。您可以通过删除字段声明
来做到这一点private int area;
并在你的方法中局部声明你的变量,所以在你的 getter:
int area = sideLength * sideLength;
return area;
但是,如果您不想每次都重复该计算,那么保留该字段是有意义的
getArea() 被调用。但是,为了做到这一点,您需要从 getter 中取出计算并放入构造函数中。
更新:
跟进 "that_other_guy" 正确答案,如果该区域在构造函数中取值,这些错误都不会发生,一切都会 return 正确结果