【问题标题】:How do I properly test the char[ ] fields in my custom object for nulls, blanks, or empty? and Why do char[ ] indicate a length of 11?如何正确测试自定义对象中的 char[ ] 字段是否为空、空白或空?为什么 char[ ] 表示长度为 11?
【发布时间】:2020-05-30 10:34:28
【问题描述】:

我正在研究如何使用反射来初始化自定义对象。举个例子, 我的对象有几个不同类型的字段,但是没有一个字段属于 字符串类型。我使用 chararrays 而不是字符串,因为我想清除对象 如果应用程序崩溃,则不必担心堆中存在不可变字符串。

另外,由于类实现了 CharSequence,静态字段 buff、offset 和 count 是必需的。另外值得一提的是,getter 和 setter 是 同步,因为此对象将在多线程环境中使用。最后, 有一个名为 People 的 Person 对象的自定义列表,它位于其自己的 People.java 文件中,并且 是 Person 对象的自定义集合。为简洁起见,省略了有关该对象的其他详细信息。

问题是,如何测试我的 Person 对象中的空、空白或空字段?在我的主要课程中, 在将所述对象插入后端数据库之前,我想测试空、空或空白。我有 尝试创建 Person.isNull() 和类似的 Person.hasNull() 函数来测试空值 在char[] 字段中,但结果绝对不是我所期望的。里面的println语句 isCharArray 的测试揭示了一些我目前不理解的事情.....

这是一些示例输出:

Size of byte: 1 bytes.
Size of short: 2 bytes.
Size of int: 4 bytes.
Size of long: 8 bytes.
Size of char: 2 bytes.
Size of float: 4 bytes.
Size of double: 8 bytes.
buff: char[] 11
personID: char[] 11
personTitle: char[] 11
personFirstName: char[] 11
personLastName: char[] 11

它是使用以下 System.out.println 语句创建的:

System.out.println(f.getName() + ": " + f.getType().getCanonicalName() + " " +  String.valueOf(value).length());

并提出 2 个问题:

  1. 为什么是 11?!!!!!!
  2. 如何正确测试空白、空或零长度字段?!!!

请帮忙....

public class Person  implements Serializable, 
                                Comparable<Person>,  
                                CharSequence, 
                                Cloneable   { // the object to model

    //  Fields 0, 1, and 2 are required to implement CharSequence                                   
    //  http://www.java2s.com/Tutorial/Java/0040__Data-Type/implementsCharSequence.htm
    private  static char[] buff = {'\0'};   // No static fields are ever                    // Field 0
    private  static int offset  = 0;        // written to file. Their values                // Field 1
    private  static int count   = 0;        // must be reconstructed.                       // Field 2  

    // default serialVersion id
    private static final long serialVersionUID = 7891011129876814235L;                      // Field 3
    private final static LocalDateTime rightNow = LocalDateTime.now();  

    private long   localSerialVersionUID= serialVersionUID;  //1st field written to file    // Field 4  
    private LocalDateTime personCreatedDateTime= rightNow;                                  // Field 5 
    private LocalDateTime  personLastUpdate    =  rightNow; // (YYYY-MM-DD)                 // Field 6  
    private char[] personID              = {'\0'}; // (PK)  possibly int auto increment     // Field 7 
    private char[] personTitle           = {'\0'};                                          // Field 8 
    private char[] personFirstName       = {'\0'};                                          // Field 9 
    private char[] personLastName        = {'\0'};                                          // Field 10 
    private LocalDate   personDOB        =  LocalDate.parse("1010-10-10"); // (YYYY-MM-DD)  // Field 11



    public Person( 
            final long serialUID,                           //4        
            final LocalDateTime createdDateTime,            //5 
            final LocalDateTime lastUpdate,                 //6
            final char[] id,                                //7 
            final char[] title,                             //8 
            final char[] firstName,                         //9 
            final char[] lastName,                          //10 
            final LocalDate   DOB                           //11                                                   
    ) {                                                
        this.localSerialVersionUID(serialUID);           //4 
        this.personCreatedDateTime(LocalDateTime.now()); //5 
        this.personLastUpdate(lastUpdate);               //6
        this.personID(id);                               //7 
        this.personTitle(title);                         //8 
        this.personFirstName(firstName);                 //9 
        this.personLastName(lastName);                   //10
        this.personDOB(DOB);                             //11
    }   

    public boolean hasNull() {
        Field fields[] = this.getClass().getDeclaredFields();

        for (Field f : fields) {
            f.setAccessible(true);

            try{
                    Object value = f.get(this);
                    if ( value == null) {return true; } // default condition

                    boolean isCharArray =  f.getType().getCanonicalName().equals("char[]" );


                    // No need to check fields that are not char[]
                    if (( isCharArray) ) {      

    // ************* this compiles and executes (doesn't crash), but it doesn't produce intended results *********

                        System.out.println(f.getName() + ": " + f.getType().getCanonicalName() + " " +  String.valueOf(value).length());

                        if ( String.valueOf(value).length() == 0)  {return true;}
                        if ( String.valueOf(value).isEmpty())      {return true;}
                        if ( String.valueOf(value).isBlank())      {return true;}
                        if ( String.valueOf(value).equals('\0'))   {return true;}

                    }   

    // ************* this compiles and executes (doesn't crash), but it doesn't produce intended results *********


                } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return false;
        }
    }         


    //enter code here


    /**
     * @param args
     */
    public static void main(String[] args)  {
        People<Person> people = new People()<>; //customized list of person objects
        People<Person> people2 = new People()<>; //customized list of person objects

        Person thomas = new Person().personFirstName("Thomas".toCharArray()); 
                // all other char array fields = {'\0'}
        people.add(thomas);

        Person sybil =  new Person().personFirstName("Sybil".toCharArray()); 
                // all other char array fields = {'\0'}
        people2.add(sybil);

        if (!thomas.hasNull() ){    // ******* currently this test fails and a Person gets inserted to the People list
            People.insertPerson(thomas);
        }
        if (!sybil.hasNull() ){     // ******* currently this test fails and a Person gets inserted to the People list
            People.insertPerson(sybil);
        }
    }
}

【问题讨论】:

  • 当您打印String.valueOf(value) 的结果时,它可能会有所帮助。然后,你就会明白了。除此之外,停止尝试将 Java 编程为 C 语言。尝试重新实现以零结尾的字符串是没有意义的。 Java 的数组不像 C 的数组那样工作,Java 的字符串不是以零结尾的字符数组。如果您需要字符串,请使用 String 并了解字符串在 Java 中的工作原理。此外,不要无缘无故实施CharSequenceCloneable。创建 constant rightNow 并为每个对象分配与其声称的创建时间相同的值也是没有意义的。
  • 1/3 Tyvm 的回复。但是,我不确定我是否需要遵循您的所有(仅部分)建议。例如,使用 rightNow() 是创建一个包含 30 个成员的对象集(例如,与人员对象相关联的位置对象,以及与其自己的位置对象相关联的学校对象),以促进记录协调。从概念上讲,对象是在同一时间范围内创建的,但秒和毫秒,甚至分钟可能会有所不同,具体取决于处理器的速度或 TOD 与滚动到另一个日期/时间的接近程度)。有没有更好的办法?
  • 1) 创建多个具有相同时间戳的对象没有问题,但是final static字段从不改变,所以在显示的代码中,所有对象都具有相同的时间戳。解决方案已在您的代码中显示,只需接收时间戳作为构造函数参数。如果这是唯一的构造函数,那么在用构造函数参数覆盖 final static 字段之前分配永不改变的值是毫无意义的。
  • 2) Java 数组的长度是固定的,所以用{'\0'} 初始化的数组不能容纳超过一个字符。出于大多数实际目的,您必须将它们替换为其他数组对象。我猜,您没有显示的 setter 方法确实已经分配了引用而不是覆盖数组内容。所以它更像是 Cargo Cult Programming,使用字符串之类的数组。在用指向其他数组的指针覆盖它们的引用之前,您已经创建了五个单长度数组。如果您使用String 并使用"" 初始化字段,那么只有一个对象而不是五个。
  • 但无论如何,在大多数情况下,垃圾收集将比每次传递数据时都必须复制数据的代码更有效。 3) 我看不到任何解释为什么需要实现CharSequence。您的代码没有使用该功能,并且任何使用该功能的尝试,因为它是在与实例无关的 static 字段之上实现的,都会产生灾难性的结果。目前尚不清楚“每个数据点必须相同”的确切含义,但更不用说Cloneable 是如何发挥作用的。这个接口只有一个用途,支持clone()方法。

标签: java arrays serialization reflection initialization


【解决方案1】:

String.valueOf().length() 返回 11,因为这是输出中的数字/字符数(即 [@936016386 - 一个地址 - 有 11 个字符)

【讨论】:

    猜你喜欢
    • 2013-03-16
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 2019-03-22
    相关资源
    最近更新 更多