有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在调用超级构造函数之前检查变量的有效性

因此,我正在编写一些代码,其中包括扩展我以前编写的一个类,在这个类中,文件是使用构造函数创建和命名的,该构造函数接受long类型的名称和大小。在原始类中,我在构造函数中验证了输入的文件名包含一个“”字符,但不需要文件的特定扩展名。对于我正在编写的这个新类,我要求名称的扩展名为“.mp3”。但是,我的编译器不喜欢在超级构造函数之前进行验证

这是我当前的代码:

public class Song extends DigitalMedia{

private String artist;
private String album;
private String name;
private long size;

public Song(String aName, long aSize, String aArtist, String aAlbum){
    super(aName, aSize);
    setArtist(aArtist);
    setAlbum(aAlbum);
}

在我创建构造函数之前,有没有办法验证“aName”是否包含“.mp3”


共 (4) 个答案

  1. # 1 楼答案

    代码执行到达constructor意味着对象处于活动状态,现在可以初始化其states(字段)

    A.java的对象也可以被称为A.java的超类的对象。在类A.java初始化状态之前,对象从超类继承属性和特性是有意义的。在超级类进行初始化之后,类A.java有机会进行初始化

    如果超类中没有参数构造函数,则隐式调用超类的构造函数,否则需要显式调用超类的任何一个参数化构造函数

    如果条件在^{中失败,您希望做什么?您可以选择抛出异常,但仍然创建了对象,您可以通过重写finalize()方法并检查this对象来验证是否存在异常。您可能希望通过调用System.gc()来影响垃圾收集器,以便代码执行更快地到达finalize()方法

    提议的解决方案 在调用构造函数之前,应该验证构造函数的参数。如果你想把它封装在你的类中,那么你可以选择添加一个非私有的静态方法(你可以把它命名为getInstance()),创建并返回类的对象Song。在这种情况下,可以将构造函数设置为私有。请注意,这将使您的类不可扩展,这只是一种设计选择

  2. # 2 楼答案

    我不能说这是否是设计程序的最佳方式,但您可以在一个super参数中调用验证器方法:

    public Song(String aName, long aSize, String aArtist, String aAlbum){
        super(validateName(aName), aSize);
        setArtist(aArtist);
        setAlbum(aAlbum);
    }
    
    private static String validateName(String name) {
        if (whatever) {
            throw new Whatever();
        }
        return name;
    }
    
  3. # 3 楼答案

    从继承的角度来看,子类实际上不应该比它的超类更严格

    但是,如果您想使子类的实例化受到更严格的限制,可以使构造函数private,并提供一个工厂方法,首先进行验证

    public class Song extends DigitalMedia {
    
        private String artist;
        private String album;
        private String name;
        private long size;
    
        private Song(String aName, long aSize, String aArtist, String aAlbum) {
            super(aName, aSize);
            setArtist(aArtist);
            setAlbum(aAlbum);
        }
    
        public static Song makeSong(String aName, long aSize, String aArtist, String aAlbum) {
            //... validation code
            return new Song(aName, aSize, aArtist, aAlbum);
        }
        ...
    }
    

    使用封装来强制执行不变量,而不是限制类型本身

  4. # 4 楼答案

    另一种解决方案是通过内置类型检查来执行规则

    您可以创建一个MediaFormat

    interface MediaFormat { }
    

    实现MediaFormatMusicFormat,允许您指定支持哪些音乐格式:

    enum MusicFormat implements MediaFormat {
        MP3("mp3");
    
        private final String format;
    
        MusicFormat(String format) {
            this.format = format;
        }
    
        @Override
        public String toString() {
            return format;
        }
    }
    

    DigitalMedia可以由MediaFormat组成:

    class DigitalMedia {
        private final MediaFormat format;
        private final String name;
    
        public DigitalMedia(String name, MediaFormat format) {
            this.name = name;
            this.format = format;
        }
    }
    

    Song可以接受MusicFormat

    class Song {
        public Song(String name, MusicFormat format) {
            super(name, format);
        }
    }
    

    这将迫使用户使用MusicFormat中指定的任何内容,避免所有那些讨厌的检查。然后可以公开一个String方法,该方法返回name + "." + format