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

如何在创建Java对象前校验参数?以点坐标校验为例

Java对象创建前的合法性校验问题

场景与现有代码

现有一个计算两点距离的程序,包含Cliente.java(负责输入输出)和Ponto.java(封装点坐标与距离计算)。

Cliente.java 代码

import java.util.Scanner;
public class Cliente {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        Ponto a = new Ponto(sc.nextDouble(), sc.nextDouble());
        Ponto b = new Ponto(sc.nextDouble(), sc.nextDouble());
        System.out.println((int) Math.floor(a.dist(b)));
        sc.close();
    }
}

你编写的有问题的 Ponto.java 代码

class Ponto {
    private double x, y;
    check(x);
    check(y);
    
    public Ponto(double x, double y) {
        this.x = x;
        this.y = y;
    }
    
    public double dist(Ponto p) {
        double dx = x - p.x;
        double dy = y - p.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
    
    public static void check(double x, double y) {
        if (x < 0 || y < 0) {
            System.out.println("iv");
        }
    }
}

需求与问题

需求是:创建Ponto对象前必须校验x、y坐标是否大于0,校验不通过则输出"iv"且不创建对象。但你编写的代码报错,且其他写法总是先创建对象再校验,不符合要求。

输入输出示例

  • 合法输入:
    0 0
    2 0
    
    输出:2
  • 非法输入:
    -1.0 1.0
    -1.0 1.0
    
    输出:iv

代码错误分析

  1. 语法错误:类体中直接写check(x); check(y);是不允许的,Java类的成员区域(变量、方法、构造器之外)不能直接执行方法调用语句,只能在方法、构造器或初始化块内执行。
  2. 校验逻辑无效:即使check方法能执行,它只是输出"iv",但没有阻止对象的创建——构造器依然会完成赋值,非法坐标的对象还是会被实例化。
  3. 构造器未做校验:当前构造器直接赋值,完全没有对坐标合法性做判断,导致非法对象被创建。

解决方案

方案1:静态工厂方法(推荐)

将构造器私有化,通过静态工厂方法控制对象创建流程,在工厂方法中完成校验,不合法则输出提示并返回null。

修改后的 Ponto.java

class Ponto {
    private double x, y;

    // 私有构造器,外部无法直接new创建对象
    private Ponto(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double dist(Ponto p) {
        double dx = x - p.x;
        double dy = y - p.y;
        return Math.sqrt(dx * dx + dy * dy);
    }

    // 静态工厂方法:负责校验并创建合法对象
    public static Ponto create(double x, double y) {
        if (x < 0 || y < 0) {
            System.out.println("iv");
            return null;
        }
        return new Ponto(x, y);
    }
}

修改后的 Cliente.java

import java.util.Scanner;

public class Cliente {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        Ponto a = Ponto.create(sc.nextDouble(), sc.nextDouble());
        Ponto b = Ponto.create(sc.nextDouble(), sc.nextDouble());
        
        // 仅当两个对象都合法时,才计算并输出距离
        if (a != null && b != null) {
            System.out.println((int) Math.floor(a.dist(b)));
        }
        sc.close();
    }
}

方案2:构造器抛出异常

在构造器中先做校验,不合法则输出提示并抛出异常,终止对象创建流程,外部捕获异常避免程序崩溃。

修改后的 Ponto.java

class Ponto {
    private double x, y;

    public Ponto(double x, double y) {
        if (x < 0 || y < 0) {
            System.out.println("iv");
            // 抛出异常终止对象创建
            throw new IllegalArgumentException("坐标不能为负数");
        }
        this.x = x;
        this.y = y;
    }

    public double dist(Ponto p) {
        double dx = x - p.x;
        double dy = y - p.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

修改后的 Cliente.java

import java.util.Scanner;

public class Cliente {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try {
            Ponto a = new Ponto(sc.nextDouble(), sc.nextDouble());
            Ponto b = new Ponto(sc.nextDouble(), sc.nextDouble());
            System.out.println((int) Math.floor(a.dist(b)));
        } catch (IllegalArgumentException e) {
            // 无需额外输出,构造器已输出"iv"
        } finally {
            sc.close();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:40:56