Java对象的奇怪行为:据说是相同的过程,结果不同

时间:2017-03-24 16:37:02

标签: java arrays object vector

我遇到了Java对象的奇怪行为。我有两个不同版本的ComponentPlane.class。差异由******标记。

第一个工作版

package app.pathsom.som.output;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

import app.pathsom.som.map.Lattice;
import app.pathsom.som.map.Node;

public class ComponentPlane extends JPanel{

private Lattice lattice;
private int componentNumber;
private double minValue;
private double maxValue;
private double origMinValue;
private double origMaxValue;

public ComponentPlane(Lattice lattice, int componentNumber){
    this.lattice = new Lattice();
    this.componentNumber = componentNumber;
    initLattice(lattice);
    initComponentPlane();
}

private void initLattice(Lattice lattice){
    this.lattice.setLatticeHeight(lattice.getLatticeHeight());
    this.lattice.setLatticeWidth(lattice.getLatticeWidth());
    this.lattice.setNumberOfNodeElements(lattice.getNumberOfNodeElements());
    this.lattice.initializeValues();
    this.lattice.setNodeHeight(lattice.getNodeHeight());
    this.lattice.setNodeWidth(lattice.getNodeWidth());

    this.lattice.setTotalNumberOfNodes(lattice.getTotalNumberOfNodes());

    for(int i = 0; i < lattice.getTotalNumberOfNodes(); i++){
        ******this.lattice.getLatticeNode()[i] = new Node(lattice.getLatticeNode()[i]);******
    }

}
}

第二个非工作版本的唯一区别是这个功能替换上面的功能

private void initLattice(Lattice lattice){
    //same code here 

    for(int i = 0; i < lattice.getTotalNumberOfNodes(); i++){
        ******this.lattice.getLatticeNode()[i] = lattice.getLatticeNode()[i];******
    }

}

我还尝试过做第三个非工作版本......

private void initLattice(Lattice lattice){
    //same code here
    ******this.lattice.setLatticeNode(lattice.getLatticeNode());******
}

Node.class中的构造函数(在第一个WORKING版本中使用了WHICH就是这个......

public Node (Node node){
    this.xPos = node.xPos;
    this.yPos = node.yPos;
    this.numOfElements = node.numOfElements;
    this.cluster = -1;
    this.nodeIndex = node.getNodeIndex();
    for(int i = 0; i < this.numOfElements; i++){
        this.addElement(node.getDoubleElementAt(i));
    }
}

Lattice.class

public class Lattice {
private int latticeWidth;
private int latticeHeight;

private int numOfNodeElements;

private int nodeWidth;
private int nodeHeight;
private int totalNumOfNodes;

private Node[] latticeNodes;

private final int MAP_RADIUS = 225;

public Lattice(int latticeWidth, int latticeHeight, int numOfNodeElements){
    this.latticeWidth = latticeWidth;
    this.latticeHeight = latticeHeight;
    this.numOfNodeElements = numOfNodeElements;

    initializeLattice();
}

public Lattice(){
    this(10, 10, 3);
}

public void initializeValues(){
    totalNumOfNodes = this.latticeHeight * this.latticeWidth;
    latticeNodes = new Node[totalNumOfNodes];   //specify the array of nodes

    nodeWidth = (int) Math.floor(450/this.latticeWidth);
    nodeHeight = (int) Math.floor(450/this.latticeHeight);
}

protected void initializeLattice(){
    totalNumOfNodes = this.latticeHeight * this.latticeWidth;
    latticeNodes = new Node[totalNumOfNodes];

    nodeWidth = (int) Math.floor(450/this.latticeWidth);
    nodeHeight = (int) Math.floor(450/this.latticeHeight);

    //initialize colors

    for(int i = 0; i <totalNumOfNodes; i++){
        latticeNodes[i] = new Node(((i % this.latticeWidth) * nodeWidth) + nodeWidth / 2, 
                ((i / this.latticeWidth) * nodeHeight ) + nodeHeight/2, numOfNodeElements, i);
        latticeNodes[i].setNodeColor(new Color((int)(latticeNodes[i].getDoubleElementAt(0) 
                * 255), (int)(latticeNodes[i].getDoubleElementAt(1) * 255), (int) (latticeNodes[i].getDoubleElementAt(2) * 255)));
    }   
}

public int getLatticeHeight(){
    return latticeHeight;
}

public void setLatticeHeight(int latticeHeight){
    this.latticeHeight = latticeHeight;
}

public Node[] getLatticeNode(){
    return latticeNodes;
}

public void setLatticeNode(Node[] latticeNodes){
    this.latticeNodes = latticeNodes;
}

public int getLatticeWidth(){
    return latticeWidth;
}

public void setLatticeWidth(int latticeWidth){
    this.latticeWidth = latticeWidth;
}

public int getNodeHeight(){
    return nodeHeight;
}

public int getNodeWidth(){
    return nodeWidth;
}

public void setNodeHeight(int nodeHeight){
    this.nodeHeight = nodeHeight;
}

public void setNodeWidth(int nodeWidth){
    this.nodeWidth = nodeWidth;
}

public int getNumberOfNodeElements(){
    return numOfNodeElements;
}

public void setNumberOfNodeElements(int numOfNodeElements){
    this.numOfNodeElements = numOfNodeElements;
}

public int getTotalNumberOfNodes(){
    return totalNumOfNodes;
}

public void setTotalNumberOfNodes(int totalNumberOfNodes){
    this.totalNumOfNodes = totalNumberOfNodes;
}
}

某个Visualization.class启动所有这些操作并存储ComponentPlane数组。这是函数

public void initComponentPlanes(){
    componentPlanes = new ComponentPlane[somtrainer.getLattice().getNumberOfNodeElements()];
    int size = somtrainer.getLattice().getNumberOfNodeElements();
    for(int i = 0; i < size; i++){
        System.out.println(i + ": " + inputData.getVariableLabels()[i] + " size : " + size);
        componentPlanes[i] = new ComponentPlane(somtrainer.getLattice(), i);
        componentPlanes[i].setBounds((240 - 225)/2, (280-240)/2, 225, 240);
        componentPlanes[i].setOrigMaxMin(maxMin[i][0], maxMin[i][1]);
    }
}

我的问题是

  • 第一个工作正常。它为每个组件编号创建HEATMAPS或COMPONENTPLANES(意味着它们彼此不同)但我不能将它用作引用(&#34; this.addElement ....&#的******的行) Node.class构造函数中的34;)给出了OUTOFMEMORY错误,所以只要我有许多COMPONENTPLANES,它就会LAGS和FREEZES。 (我实际上在做一个COMPONENTPlane对象的ARRAY)所以我决定尝试第二个和第三个选项。我已经增加了我的堆大小所以这是不可能的

  • 如果我使用第二个和第三个,我最终没有LAGS,即使有大量的ComponentPlanes(可能因为创建新的Node对象或idk而占用的内存较少)但这些会产生错误的热图。所有的热图都是一样的。事实是,所有的热图都像是ComponentPlanes数组的最后一个元素(例如,如果我有十个ComponentPlane对象,所有的热图看起来都像第十个组件对象)

所有的热图都是这样的 - 与数组中的最后一张热图相同:

Image

有没有办法让第二个和第三个工作?

1 个答案:

答案 0 :(得分:0)

显而易见的区别在于,在第一个中您创建了新节点,而在其他节点中,您重新使用旧节点。这条线

this.lattice.getLatticeNode()[i] = lattice.getLatticeNode()[i];

将一个对象设置为另一个。如果稍后lattice.getLatticeNode()[i]的属性发生更改,则也会影响this.lattice.getLatticeNode()[i]。这可能导致难以发现的错误。相反,行

this.lattice.getLatticeNode()[i] = new Node(lattice.getLatticeNode()[i]);

正在创建一个与旧对象不同的新对象。但是,当然,这意味着您正在使用更多内存,因为现在您有两个对象而不是一个。

您可以采取一些措施来减少使用的内存量。 private final int MAP_RADIUS = 225;可以设为静态,因此不会为每个节点创建常量的新副本。