想象一下,我有一些看起来像这样的类:
class Car {
private Image carImage;
public Car(int imageIndex) {
switch (imageIndex) {
case 1: carImage = generateCarImage(1); break;
# and so forth
}
}
}
class Audi extends Car {
private int numberOfSeats;
public Audi(int imageIndex, int numberOfSeats) {
super(imageIndex);
this.numberOfSeats = numberOfSeats;
}
}
现在想象一下,我使用相同的图像创建了多个奥迪:
Audi car1 = new Audi(1,2);
Audi car2 = new Audi(1,3);
car1和car2会延伸同一个物体吗?我假设没有,但有没有办法可以做到这一点?我问,因为我想避免两次生成和存储相同的图像。
编辑:
这两个奥迪将参考同一辆车,例如图像只生成并存储一次,对一个图像的任何更改都会影响另一个图像?
class Car {
private Image carImage;
public Car(int imageIndex) {
switch (imageIndex) {
case 1: # carImage = readfile(1.jpeg)
# and so forth
}
}
}
class Audi{
private int numberOfSeats;
private Car car;
public Audi(Car car, int numberOfSeats) {
this.car = car;
this.numberOfSeats = numberOfSeats;
}
}
Car car = new Car(1);
Audi audi1 = new Audi(car,2);
Audi audi2 = new Audi(car,2);
编辑2:
这里有很多好的答案,我最后结合使用它们来创造一个不错的解决方案。我最初的问题并没有很好地定义,主要是因为我并不确切地知道自己到底是什么。
无论如何,对于这个问题,不可能事先生成所有数据(下面的例子中的PartsInfo
),也不能显式生成数据(如上面的switch-case例子所暗示的那样)。下面解决方案的最大问题是我无法访问PartsInfo
中的各个字段而无需检索整个事物(如调用Car.getPartsInfo()时在解决方案中所做的那样)或创建多个实例相同的对象(在这种情况下,Car类将获得自己的PartsInfo变量)。
弱散列图也可以,但不是最佳的,因为问题不是垃圾收集,而是存储在不同实例中的大量相同数据。
如果ID类似于" audi-a4-2003"该解决方案适用。并且PartsInfo
对于所有人来说是相同的#aud;-a4-2003"独立于颜色,所有者,年龄,座位数等,但与#34; audi-a4-2004"完全不同。
谢谢
Class PartsInfo {
// lots of stuff I'd rather not create nor save multiple times
}
Class PartsInfoFactory {
private static HashMap<String, PartsInfo> partsInfoMap = new HashMap<String, PartsInfo>();
public static getPartsInfo(String id) {
if (!partsInfoMap.containsKey(id)) {
generatePartsInfo(id);
}
return partsInfoMap(id)
}
private static generatePartsInfo(String id) {
// Do stuff I don't want to do twice for same ID
partsInfoMap.put(id)
}
}
Class Car {
private Color color;
private String id;
// Notice that PartsInfo is not stored here
public Car(Color color, String id) {
this.color = color;
this.id = id;
}
public PartsInfo getPartsInfo() {
return PartsInfoFactory.getPartsInfo(id);
}
}
答案 0 :(得分:5)
car1
和car2
会扩展相同的对象吗?
一个类可以从另一个类扩展。对象不会扩展任何东西。在Java中,继承仅适用于类和接口。您在此处所做的是创建同一班级的两个实例,Audi
和Audi
从Car
延伸。
有没有办法可以做到这一点?
没有
我问,因为我想避免生成和存储两次相同的图像。
这是一个值得回答的正确问题。您真正的问题是避免多次创建相同的对象实例。为此,最好使用WeakHashMap
来使用对象池。以下是对使用此结构的原因的解释:When would you use a WeakHashMap or a WeakReference?
答案 1 :(得分:4)
避免多次创建同一图像的好方法是使用依赖注入:将图像作为构造函数参数注入,而不是将参数传递给generateCarImage
:
class Car {
private final Image image;
Car(Image image) {
this.image = image;
}
}
class Audi extends Car {
Audi(Image image, int numDoors) {
super(image);
// ...
}
}
这意味着image
可以来自任何地方 - 让您更明确地控制图像的生命周期。所以,如果你想一遍又一遍地使用相同的图像,你可以,并且很明显你是:
Image image = generateCarImage(1);
Audi car1 = new Audi(image, 4);
Audi car2 = new Audi(image, 2);
此外,通过删除与generateCarImage
方法的静态耦合,它使类更易于测试,因为您可以创建不同的图像进行测试,例如生成起来比较简单。
答案 2 :(得分:3)
你永远不会扩展对象,你扩展了类。当然,你会一直扩展同一个班级。
答案 3 :(得分:2)
在Java中没有扩展对象这样的东西(其他语言都有这种继承,称为 prototypal 。但是,Java没有原型继承;只有类继承)。
在Java中扩展意味着扩展一个类,而不是一个对象,它是一个类的实例。
因此,尽管car1
和car2
的类扩展了同一个类,但这两个对象彼此无关。
我想避免生成和存储两次相同的图像
多个对象共享第三个对象没有问题,在您的情况下可能是图像。处理此问题的一种方法是创建Car
的所有实例共有的图像缓存,在第一次请求时生成图像,然后根据需要重新使用相同的图像对象以节省空间: / p>
是否有可能不是搜索图像缓存,而是搜索
Car
的所有实例的缓存,然后选择在Audi
类中实例化哪一个?
您无法再次实例化对象。但是,您可以创建Car
个对象的缓存,并在Car
上实现一个工厂方法,该方法在创建新实例之前在其缓存中搜索合适的汽车。
答案 4 :(得分:2)
每当你使用new子句时,你将创建一个对象的新实例,一个完整的单独的类表示;所以回答直接的问题:不,你没有扩展对象。
潜在的问题是你可能不想重复创建相同的图像:然后你必须采取不同的方法。我首先建议对Java的OO方面进行另一次读取,然后考虑(可能)工厂模式,这可能是一个类,如果已经创建了另一个,它将负责不重复创建相等的图像。
答案 5 :(得分:2)
我的解决方案是使用静态引用作为常量值。这是最简单的解决方案,因为enum
不能与对象一起使用,因为它必须在编译时进行评估。
但是我们想要获得运行时常量,以及使用类似于使用单实例的枚举的好处,并且可以在switch语句中使用。
因此,我们将实现enum
以返回在编译时可用的另一个类的常量静态属性,并返回对在运行时创建的对象的常量引用。
class CarImageDirectory
{
// Created at Run-time
public static final Image Audi = new Image("Audi");
public static final Image Toyota = new Image("Toyota");
// ..etc
}
enum CarImage
{
// Created at Compile-time
Audi
{
@Override public Image image () { return CarImageDirectory.Audi; }
},
Toyota
{
@Override public Image image () { return CarImageDirectory.Toyota; }
}; // ..etc
public abstract Image image ();
}
CarImage将如下工作:
CarImage A = CarImage.Audi;
CarImage B = CarImage.Audi;
if (A == B) System.out.println("A and B are both Audi");
然后我们用它来定义我们的Car类:
class Car
{
private CarImage carImg;
public Car (CarImage carImg) { this.carImg = carImg; }
public Image getImage () { return carImg.image(); }
public CarImage getCarImage () { return carImg; }
}
class AudiCar extends Car
{
private int numOfSeats;
public AudiCar (int numOfSeats)
{
super(CarImage.Audi);
this.numOfSeats = numOfSeats;
}
}
class ToyotaCar extends Car
{
private int numOfSeats;
public ToyotaCar (int numOfSeats)
{
super(CarImage.Toyota);
this.numOfSeats = numOfSeats;
}
}
同样CarImage
本身也可用于switch
语句:
CarImage A = CarImage.Audi;
switch(A)
{
case CarImage.Audi:
System.out.println("This car is Audi");
break;
case CarImage.Toyota:
System.out.println("This car is Toyota");
break;
default:
}
答案 6 :(得分:1)
您是否研究过"flyweight"模式?这可能会减少对象的创建。 从技术上讲,它可以减少内存占用,但如果对象创建成本高且重用率高,则可以在启动时间不存在的情况下使用它,例如应用程序服务器启动时。
在任何情况下,只有在您知道时才会优化,这是一个性能问题。
希望这有帮助!