You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java三角形类复制构造函数空引用拷贝测试失败求助

复制构造函数测试失败问题排查

问题背景

学习中级Java课程,需实现一个封装的三角形类,核心要求包括:

  • 验证给定边长是否构成有效三角形(边长为正且满足三角不等式)
  • 实现复制构造函数:Triangle(Triangle triangle),复制传入对象的实例变量;若传入引用为null,则用DEFAULT_SIDE初始化所有边长

当前复制构造函数在空引用测试中失败,测试提示:"Copy of null ==> expected: <1.0> but was: <0.0>"

现有复制构造函数代码

public Triangle(Triangle triangle)
{
    Triangle newTriangle = new Triangle();
    
    if (triangle != null)
    {
        if (isTriangle(triangle.getSideA(), triangle.getSideB(), triangle.getSideC()))
        {
            newTriangle.setSideA(triangle.getSideA());
            newTriangle.setSideB(triangle.getSideB());
            newTriangle.setSideC(triangle.getSideC());
        }
    }
    else 
    {
        newTriangle.setSideA(DEFAULT_SIDE);
        newTriangle.setSideB(DEFAULT_SIDE);
        newTriangle.setSideC(DEFAULT_SIDE); 
    }
}

测试代码片段

@Test
void testCopyConstructor() {
    // Test invalid input.
    Triangle triangle = null;
    Triangle copy = new Triangle(triangle);
    double[] expected = {1, 1, 1};
    String msg = "Copy of null";
    checkSides(copy, expected, msg);
    // ... 其他测试代码
}

完整Triangle类代码

public class Triangle {

    private double sideA;
    private double sideB;
    private double sideC;
    
    public final static String POLYGONSHAPE = "Triangle";
    
    public final static double DEFAULT_SIDE = 1;
    
    //CONSTRUCTORS
    
    public Triangle()
    {
        this.sideA = DEFAULT_SIDE;
        this.sideB = DEFAULT_SIDE;
        this.sideC = DEFAULT_SIDE;
    }
    
    public Triangle(double sideA, double sideB, double sideC)
    {
        if (isTriangle(sideA,sideB,sideC))
        {
            this.sideA = sideA;
            this.sideB = sideB;
            this.sideC = sideC;
        }
        else
        {
            sideA = DEFAULT_SIDE;
            sideB = DEFAULT_SIDE;
            sideC = DEFAULT_SIDE;
        }
    }
    
    public Triangle(double[] sides)
    {
        this();
        
        if (isTriangle(sides))
        {
            this.sideA = sides[0];
            this.sideB = sides[1];
            this.sideC = sides[2];
        }
        else 
        {
            this.sideA = DEFAULT_SIDE;
            this.sideB = DEFAULT_SIDE;
            this.sideC = DEFAULT_SIDE;
        }
    }
    
    public Triangle(Triangle triangle)
    {
        Triangle newTriangle = new Triangle();
        
        if (triangle != null)
        {
            if (isTriangle(triangle.getSideA(), triangle.getSideB(), triangle.getSideC()))
            {
                newTriangle.setSideA(triangle.getSideA());
                newTriangle.setSideB(triangle.getSideB());
                newTriangle.setSideC(triangle.getSideC());
            }
        }
        else 
        {
            newTriangle.setSideA(DEFAULT_SIDE);
            newTriangle.setSideB(DEFAULT_SIDE);
            newTriangle.setSideC(DEFAULT_SIDE); 
        }
    }
    
    //SIDE GETTERS
    
    public double getSideA()
    {
        return sideA;
    }
    
    public double getSideB()
    {
        return sideB;
    }
    
    public double getSideC()
    {
        return sideC;
    }
    
    public double[] getSides()
    {
        double[] sides = {sideA, sideB, sideC};
        
        return sides;   
    }
    
    //ANGLE GETTERS
    
    public double getAngleA()
    {
        double angleA = lawOfCosines(sideB, sideC, sideA);
        
        return angleA;      
    }
    
    public double getAngleB()
    {
        double angleB = lawOfCosines(sideC, sideA, sideB);
        
        return angleB;  
    }
    
    public double getAngleC()
    {
        double angleC = lawOfCosines(sideA, sideB, sideC);
        
        return angleC;      
    }
    
    public double[] getAngles()
    {
        return new double[] {getAngleA(), getAngleB(), getAngleC()};
    }
    
    //SIDE SETTERS
    
    public boolean setSideA(double sideA)
    {
        if (isTriangle(sideA, sideB, sideC))
        {
            this.sideA = sideA;
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    public boolean setSideB(double sideB)
    {
        if (isTriangle(sideA, sideB, sideC))
        {
            this.sideB = sideB;
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    public boolean setSideC(double sideC)
    {
        if (isTriangle(sideA, sideB, sideC))
        {
            this.sideC = sideC;
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    public boolean setSides(double[] sides)
    {
        if (isTriangle(sides))
        {
            this.sideA = sides[0];
            this.sideB = sides[1];
            this.sideC = sides[2];
            return true;
        }
        else
        {
            return false;
        }
        
    }
    
    //HELPER METHODS
    
    public static boolean isTriangle(double a, double b, double c)
    {
        //check if sides are positive
        if (a > 0 && b > 0 && c > 0)
        {
            //check if they satisfy triangle inequality
            if ((a + b) > c && (a + c) > b && (b + c) > a)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else {
            return false;
        }
        
    }
    
    public static boolean isTriangle(double[] sides)
    {
        
        if (sides == null || sides.length != 3 || sides[0] <= 0 || sides[1] <= 0 || sides[2] <= 0 || sides[0] + sides[1] <= sides[2] || sides[0] + sides[2] <= sides[1] || (sides[1] + sides[2]) <= sides[0])
        {
            return false;
        }
        else 
        {
            return true;
        }

            }
    
    public static double lawOfCosines(double a, double b, double c)
    {
        double angle; 
        
        //find angle in radians
        angle = Math.toDegrees(Math.acos((Math.pow(b, 2) + Math.pow(a, 2) - Math.pow(c, 2))/(2.0 * a * b)));
                
        return angle;
    }
    
    public String toString()
    {
        String output = String.format("%s(%.4f, %.4f, %.4f)", POLYGONSHAPE, this.sideA, this.sideB, this.sideC);
        return output;
    }
    
    
    }

问题根源

  1. 核心错误:复制构造函数中创建了局部对象newTriangle并对其赋值,但完全没有初始化当前对象(this)的成员变量。Java中成员变量默认值为0.0,所以测试获取到的边长是0.0而非预期的1.0。
  2. 额外逻辑偏差:原代码中额外添加了isTriangle验证,但需求明确要求直接复制传入对象的实例变量,无需二次验证有效性。
  3. 其他潜在问题:三参数构造函数的else分支中,未使用this前缀,导致赋值给了局部参数而非成员变量,会引发类似的默认值问题。

修正方案

修正后的复制构造函数

public Triangle(Triangle triangle) {
    if (triangle != null) {
        // 直接复制传入对象的成员变量,遵循需求要求
        this.sideA = triangle.getSideA();
        this.sideB = triangle.getSideB();
        this.sideC = triangle.getSideC();
    } else {
        // 传入null时用默认值初始化当前对象
        this.sideA = DEFAULT_SIDE;
        this.sideB = DEFAULT_SIDE;
        this.sideC = DEFAULT_SIDE;
    }
}

修正三参数构造函数的else分支

public Triangle(double sideA, double sideB, double sideC)
{
    if (isTriangle(sideA,sideB,sideC))
    {
        this.sideA = sideA;
        this.sideB = sideB;
        this.sideC = sideC;
    }
    else
    {
        // 添加this前缀,赋值给成员变量
        this.sideA = DEFAULT_SIDE;
        this.sideB = DEFAULT_SIDE;
        this.sideC = DEFAULT_SIDE;
    }
}

验证要点

  • 测试空引用场景:确认新对象的边长均为DEFAULT_SIDE(1.0)
  • 测试有效三角形复制:确认新对象与原对象边长完全一致
  • 测试无效三角形复制:确认新对象复制原对象的无效边长(若需求允许)

内容的提问来源于stack exchange,提问作者Aly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:20:33