1.hashCode()方法与HashSet集合
如果想查找一个集合中是否包含有某个对象,大概的程序代码怎样写呢?当发现某个元素与要查找的对对象进行equals方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则返回否定的信息。如果是一个集合中有很多元素,譬如有一万个元素,并且没有包含要查找的对象时,则意味着你的程序需要从该集合中取出一万个元素进行啄一的比较才能得到结论,有人发明了一种hashCode算法,来提高查找的效率,这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储在哪个区域,
hashSet就是采用哈希算法存储对象的集合,它内部采用对某个数字n进行取余的方式对哈希码进行分组的划分对象的存储区域。Object中的hashCode用来返回对就java对象的哈希码,从而提高查找的效率。
为了保证一个类的实例对象能在HashSet正常存储,要求这个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,也就是说,如果obj1.equals(obj2)的结果为true,那么一下表达式的结果页要为true。
obj1.hashCode() == obj2.hashCode()
如果一个类的hashCode()方法没有遵循上述要求,那么,当这个的两个实例对象用equals()方法比较的结果相等时,它们本来应该无法同时存储进Set集合中,但是,如果将它们存储进HashSet集合中时,由于它们的hashCode()方法的返回值不同,第二个对象首先按哈希码计算可能会被放进与第一个对象不同的区域中,这样,它就不可能与第一个对象进行equals方法比较了,也就可能被存储进HashSet集合中了。Object类的hashCode()方法不能满足对象被存入到HashSet中的要求,因为它的返回值是通过对象的内存地址推算出来的,同一个对象在程序运行期间的任何时候返回的哈希值都是始终不变的,所以,只要是两个不同的实例对象,即使它们的equals方法比较结果相等,它们默认的hashCode方法的返回值是不同的。
提示:
(1)通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,但反之则不成立,即euqlas方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较的结果可以不等,例如,字符串“BB”和"Aa"的euqals方法比较结果肯定不相等,但它们的hashCode方法返回值却相等。
(2)当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在cantains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果。这也会导致从HashSet集合中单独删除当前对象,从而造成内存泄露。
2.通过类加载器加载配置文件:
//通过类加载器加载配置文件
//InputStream is =Test.class.getClassLoader().getResourceAsStream("com/reflect/pci.propertier");
InputStream is =Test.class.getResourceAsStream("pci.propertier");
Properties prop = new Properties();
prop.load(is);
is.close();
3.Java Bean
n的中文含义是“豆子”,顾名思义,JavaBean是指一段特殊的Java类,
就是有默然构造方法,只有get,set的方法的java类的对象.
专业点解释是:
JavaBean定义了一组规则
JavaBean就是遵循此规则的平常的Java对象
满足这三个条件:
1.执行java.io.Serializable 接口
2.提供无参数的构造器
3.提供getter 和 setter方法访问它的属性.
我自己定义了一个Person类,通过java Bean实现对成员变量的访问
public static void setProperty(Object p,String propertyName,Object value) //set方法
throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor pt = new PropertyDescriptor(propertyName, p.getClass());
Method setMethod = pt.getWriteMethod();
setMethod.invoke(p, value);//执行Person类的set方法
}
public static Object getProperty(Object p,String propertyName) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {//get方法
PropertyDescriptor pt = new PropertyDescriptor(propertyName, p.getClass());
Method getMethod = pt.getReadMethod();
Object retValue = getMethod.invoke(p, null);//执行Person的get方法
return retValue;//返回值
}
其调用如下:
Person p1 = new Person("张三", 15);
String propertyName = "age";;
System.out.println(getProperty(p1,propertyName));
Object value = 7;
setProperty(p1,propertyName,value);
System.out.println(getProperty(p1,propertyName));
使用BeanUitls工具包:
BeanUtils.setProperty(p1, "name", "hello");
//最后一个参数都是字符串
BeanUtils.setProperty(p1, "age", "12");
//最后一个从参数根据第二个参数类型判断,一致就行
PropertyUtils.setProperty(p1, "age", 12);
//上面2句执行效果一样
System.out.println(BeanUtils.getProperty(p1, "age"));
假设我在Person类中加入Date类型变量:
public class Person {
private Date birthday = new Date();
private String name;
private int age;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setages(int[] ages){
this.age = ages[0];
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
我们知道Date里面有一个
setTime(long date) 使用给定毫秒时间值设置现有 Date 对象。 |
如果我们要指定这个函数的值,我们可以如下操作:
BeanUtils.setProperty(p1, "birthday.time", "111");
System.out.println(BeanUtils.getProperty(p1, "birthday.time"));