2

我收到一条错误消息,指出“找不到方法 - getCenter”,但是每当我将“objects.get(i)”替换为像 a、b 或 d 这样的单个对象时,它都能找到该方法。我不明白为什么它无法从 ArrayList 中找到方法。

public class TestPoly
{
public static void main (String []args)
{
    ArrayList objects = new ArrayList();

    Circle2 a = new Circle2(33,10,4);
    Cylinder2 b = new Cylinder2(21,15,40,5);
    Oval2 c = new Oval2(3,7,34,10);
    OvalCylinder2 d = new OvalCylinder2(5,11,5,5,7);

    objects.add(a);
    objects.add(b);
    objects.add(c);
    objects.add(d);

    for (int i = 0; i < objects.size(); i++)
    {
        System.out.println("For " + objects.get(i).getClass().getName() + objects.get(i).getCenter());
    }
}
}

Circle2就是这个。

public class Circle2
{
// instance variables 
private int x;
private int y;
private int radius;

/**
 * Constructor for objects of class circle
 */
public Circle2(int p_x, int p_y, int r)
{
    // initialise instance variables
    x = p_x;
    y = p_y;
    radius = r;
}

public int getRadius()
{

    return radius;
}

public String getCenter()
{
    return " the center is at (" + x + "," + y + ")";
}
}

Cylinder2、Oval2 和 OvalCylinder2 都只是 Circle2 的子类。

4

4 回答 4

5

您尚未为您的 声明类型参数或类型参数ArrayList,因此它默认为Object. Object没有getCenter()方法。

您可以将ArrayList声明更改为:

ArrayList<Circle2> objects = new ArrayList<Circle2>();
Circle2 a = new Circle2(33,10,4);
objects.add(a);
objects.get(0).getCenter();

但它现在只能接受Circle2对象。

于 2013-03-28T18:37:40.657 回答
3

您正在创建一个ArrayList没有任何类型参数的对象,这意味着您将其创建为Raw Type。当您这样做时,您需要在从列表中获取对象时将它们转换为适当的类型。

要在这种情况下正确运行您的代码,这是推荐的方式,请指定这样的类型参数 -

// if you are using jdk 7 or above
ArrayList<Circle2> objects = new ArrayList<>();

或者 -

ArrayList<Circle2> objects = new ArrayList<Circle2>(); 

在此处查看有关泛型的更多信息。

但是,如果您仍然想让现有代码工作(不推荐),那么使用这个 -

ArrayList objects = new ArrayList();

Circle2 a = new Circle2(33,10,4);
Cylinder2 b = new Cylinder2(21,15,40,5);
Oval2 c = new Oval2(3,7,34,10);
OvalCylinder2 d = new OvalCylinder2(5,11,5,5,7);

objects.add(a);
objects.add(b);
objects.add(c);
objects.add(d);

for (int i = 0; i < objects.size(); i++)
{
    Circle2 circle = (Circle2 )objects.get(i);
    System.out.println("For " + circle.getClass().getName() + circle.getCenter());
}

不要以这种方式使用原始类型。它们不打算在新代码中使用,支持它们只是为了向后兼容。从上面关于原始类型的链接 -

原始类型出现在遗留代码中是因为许多 API 类(例如 Collections 类)在 JDK 5.0 之前不是通用的。使用原始类型时,您基本上会获得预泛型行为。

于 2013-03-28T18:40:28.763 回答
1

你现在拥有的当前数组列表......将“对象”作为它的元素......因此......它的元素将只支持在对象上定义的方法(toString、getHashcode 等)

您可以定义如下类型:

ArrayList<Circle2> objects = new ArrayList<Circle2>();

但是,它只能接受圆形类型的对象。以下几行将导致错误:

objects.add(b);
objects.add(c);
objects.add(d);

一个更好的方法是使用继承......所以你将有一个名为 shape 的基类......它将有一个名为 getCenter 的方法,该方法将被子类覆盖(如果需要)

public abstract class Shape {
  public String getCenter();
}

有四个类扩展了形状类:

public class Cylinder extends Shape
public class Circle extends Shape

等等

所以现在你可以让你的数组列表为:

ArrayList<Shape> shapes = new ArrayList<Shape>();

并在其中添加多个不同的形状:

shapes.add(new Circle())
shapes.add(new Cylinder())
...

以下代码是可能的

for(Shape shape : shapes)
   System.out.println(shape.getCenter())
于 2013-03-28T18:46:06.863 回答
0

一个ArrayList(或任何其他集合)需要知道它要存储的对象的类别。如果未指定,则假定您将存储Object实例。

要指定您的集合将存储的类,您需要在创建集合时包含类名:

// ...
ArrayList<Circle2> objects = new ArrayList<Circle2>();
// ...

现在您可以通过ArrayList两种方式阅读:

“数组”样式:您使用索引来遍历您的每个条目ArrayList

for(i=0; i<objects.size(); i++) {
    // Use objects(i) to get the Circle2 instance
}

'iterator' 风格:存储在集合中的对象可以通过迭代集合来读取:

for(Circle2 c : objects) {
    /*
     * The object 'c' stores every single Circle2 instance in your 'objects' list
     */
}

我建议你检查CollectionsGenerics教程:

于 2013-03-28T18:48:08.033 回答