【发布时间】: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 个问题:
- 为什么是 11?!!!!!!
- 如何正确测试空白、空或零长度字段?!!!
请帮忙....
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 中的工作原理。此外,不要无缘无故实施CharSequence或Cloneable。创建 constantrightNow并为每个对象分配与其声称的创建时间相同的值也是没有意义的。 -
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