Object类的使用
概念
- Object 类是所有Java类的根父类
- 如果在类的声明中未使用
extends
关键字指明其父类,则默认父类为java.lang.Object
类 Object
类中的功能(属性、方法)就具有通用性。
equals()
概念
- 使用在引用数据类型中。
- Object类中的equals()方法,相当与
==
;特殊的,String、Date、File、包装类等都重写了equals()
方法,所以比较的是对象中的内容。
public boolean equals(Object obj) {
return (this == obj);
}
举例
public class ObjectTest {
public static void main(String[] args) {
// 基本数据类型 ==
int a = 10;
int b = 10;
System.out.println("int类型比较:" + (a == b));// true
// Char类型
char c1 = 65;
char c2 = 'A';
System.out.println("char类型比较" + (c1 == c2));// true
// 基本数据类型自动提升
int c = 65;
System.out.println("char与int比较:" + (c == c1));// true
System.out.println("char与int比较:" + (c == c2));// true
float f1 = 65.0f;
System.out.println("int与float比较:" + (c == f1));// true
// 引用数据类型==
Object object1 = new Object();
Object object2 = new Object();
System.out.println(object1 == object2);// false
String s1 = new String("A");
String s2 = new String("A");
System.out.println(s1 == s2);// false
System.out.println("****************");
// equals
System.out.println(object1.equals(object2));// true
System.out.println(s1.equals(s2));// false
// 通过以上引用数据类型发现:普通类中没有重写equals方法,导致使用object类中的
// equals方法比较的,相当与==。而特殊的date、string类,都重写了equals方法,所以使用
// 的比较都是内容的比较
}
}
自定义equals()
通常情况下,我们自定义使用equals()
方法的话,一般也是想比较两者的内容,而不是地址值。一般的我们是去比较类中的全部/部分属性内容是否一致。
举例
定义Person类,属性name
和age
和id
public class Person {
String name;
int age;
int id = 1001;// 身份证号
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void eat() {
System.out.println("人吃饭");
}
public void walk() {
System.out.println("人说话");
}
@Override
public boolean equals(Object anObject) {
// 判断两个是否是同一对象
if (this == anObject) {
return true;
}
// 判断是否是Person类
if (anObject instanceof Person) {
// 强转成Person
Person p = (Person) anObject;
if (this.age == p.age && this.name.equals(p.getName())) {
return true;
}
}
// 判断
return false;
}
}
测试
// 重写equals
System.out.println("****************");
Person p1 = new Person("wr", 18);
Person p2 = new Person("wr", 18);
System.out.println(p1.equals(p2));
自动生成equals()
自己编写的equals()
类可能存在一些问题,我们可以使用编辑器自带的生成工具。
shift
+alt
+s
→Generate hashCode() and equals()
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
equals()练习
编写Order
类,有int
类型的orderId
,String
类型的orderName
,相应的getter
和setter
方法,两个参数的构造器,重写父类的equals()
方法,并测试判断类中的两个对象是否相等。
package com.eachwang.www.exer1;
import org.junit.Test;
public class Order {
private int orderId;
private String orderName;
public Order() {
super();
}
//
// public Order(int orderId, String orderName) {
// super();
// this.orderId = orderId;
// this.orderName = orderName;
// }
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
} if (getClass() != obj.getClass()) {
return false;
}
Order od = (Order) obj;
if (this.orderId != od.orderId) {
return false;
}
if (this.orderName == null) {
if (od.orderName != null) {
return false;
}
} else if (!this.orderName.equals(od.orderName)) {
return false;
}
return true;
}
// 测试
@Test
public void Test() {
// 测试类只能有一个构造方法
// Order o1 = new Order(1, "零食");
// Order o2 = new Order(2, "零食");
// Order o3 = new Order(3, "日常用品");
// Order o4 = new Order(3, "杂货");
// Order o5 = new Order(3, "杂货");
Order o1 = new Order();
o1.orderId = 1;
o1.orderName = "零食";
Order o2 = new Order();
o2.orderId = 2;
o2.orderName = "零食";
Order o3 = new Order();
o3.orderId = 3;
o3.orderName = "日常用品";
Order o4 = new Order();
o4.orderId = 3;
o4.orderName = "杂货";
Order o5 = new Order();
o5.orderId = 3;
o5.orderName = "杂货";
System.out.println("ordid不一样name一样:" + (o1.equals(o2)));
System.out.println("ordid不一样name不一样:" + (o1.equals(o3)));
System.out.println("ordid一样name不一样:" + (o3.equals(o4)));
System.out.println("ordid一样name一样:" + (o4.equals(o5)));
}
}
面试题
- == 和 equals()方法的区别
- ==
==
是运算符。- 使用在基本数据类型和引用数据类型中。
- 基本数据类型:比较的是两个数值的是否相同。
- 引用数据类型:比较的是两个类的地址值是否相同。两个引用是否指向同一个对象。
- equals
equals()
是方法- 使用在引用数据类型中。
- Object类中的equals()方法,相当与
==
;特殊的,String、Date、File、包装类等都重写了equals()
方法,所以比较的是对象中的内容。
- ==
public boolean equals(Object obj) {
return (this == obj);
}
toString()方法
- toString()方式java.lang.Object类中定义的方法。 1. 输出一个对象的引用时,实际上就是调用的当前对象的toString()方法
- Object类中toString()类的定义:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
- 特殊的,像Date、File、String、包装类等都重写了toString()方法,所以在调用对象的toString()方法的时候,返回“实体内容”信息
- 重写toString()方法
shift
+alt
+s
→Generate toString()
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", id=" + id + "]";
}
JUnit单元测试
步骤:
- 导包:Junit 4
- 创建Java类,进行单元测试
- Java类要求:此类是public的,提供公共无参的构造器
- 此类中声明单元测试方法
- 方法的权限是public
- 没有返回值
- 无形参
- 单元测试方法上面添加注解
@Test
,导包
import org.junit.Test;
public class JunitTest {
int a = 10;
public JunitTest() {
}
@Test
public void test1() {
System.out.println(111);
// 调用属性
System.out.println(a);
// 调用方法
show();
}
@Test
public void test2() {
System.out.println(4444);
}
private void show() {
System.out.println("222");
}
}
包装类的使用
概念
基本数据类型转包装类
- 通过构造器将基本数据类型转换成包装类
- 基本数据类型转包装类,构造器中可以传入相应的基本类型值、String类型值、可以自动提升的类型数值
- 注意
Boolean
类型,构造器传入String
类型数据为true
和false
都可以**(忽略大小写)**,传入其他值都为false
。 Boolean
类型String
形参构造器中的详细源码:
@Deprecated(since="9")
public Boolean(String s) {
this(parseBoolean(s));
}
public static boolean parseBoolean(String s) {
return "true".equalsIgnoreCase(s);
}
举例
@Test
public void test1() {
// 基本数据类型转包装类
int i1 = 10;
Integer in1 = new Integer(i1);
String s1 = "10";
Integer in2 = new Integer(s1);
System.out.println(in1.toString());// 20
System.out.println(in2);// 10
// 注意String类型必须是相应类型,不然会出现类型格式化错误
// NumberFormatException
// String s2 = "12a";
// Integer in3 = new Integer(s2);
// System.out.println(in3);
float f1 = 12.2f;
Float fl1 = new Float(f1);
System.out.println(fl1.toString());// 12.2
boolean bool = true;
Boolean B = new Boolean(bool);
System.out.println(B.toString());// true
// 注意Boolean类型
String str1 = "true";
String str2 = "TrUe";
String str3 = "truea";
System.out.println(new Boolean(str1));// true
System.out.println(new Boolean(str2));// true
System.out.println(new Boolean(str3));// false
}
包装类转基本数据类型
- 通过包装类(XXX)调用
xxxValue()
方法,就可以转成基本数据类型 - 举例:
- Integer in1 ; in1.intValue();
- Boolean bool1 ; bool1.booleanValue();
- Float fl1; fl1.floatValue();
- 数据类型高的可以转换为低的数据类型,比如Flaot类型包装类可以转换成int、float、byte等
- Float fl1 ; fl1.floatValue();fl1.intValue();fl1.byteValue();
举例
// 包装类转基本数据类型
@Test
public void test2() {
Integer in1 = new Integer(10);
int i1 = in1.intValue();
System.out.println(i1);// 10
Float fl1 = new Float(11.1f);
float f1 = fl1.floatValue();
System.out.println(f1);// 11.1
//降级float降级到int
fl1.intValue();
Boolean bool = new Boolean("asdf");
boolean b = bool.booleanValue();
System.out.println(b);// false
}
新特性:自动装箱与自动拆箱
- JDK5.0以后,可以实现不通过构造器的方式进行基本数据类型转包装类
- JDK5.0以后,可以实现不通过调用
xxxValue()
方法进行包装类转基本数据类型 - 自动装箱格式:
包装类 变量名 = 基本数据类型
- 自动拆箱格式:
基本数据类型 变量名 = 包装类对象名
举例
@Test
public void test3() {
//自动装箱与自动拆箱
//自动装箱
int i1 = 10;
Integer in1 = i1;
System.out.println(in1.toString());//10
//自动拆箱
int i2 = in1;
System.out.println(i2);//10
}
基本数据类型\包装类转成String
- 方式1:通过连接符
String 名称 = 基本数据类型名 + ""
- 方式2:通过
String.valueOf(xxx)
方法
举例
@Test
public void test4() {
// 基本数据类型\包装类转成String
// 方式1:连接符
int i1 = 10;
String str1 = i1 + "";
// 方式2:valueOf()方法
Integer in1 = i1;
String str2 = String.valueOf(in1);//调用的是形参Object
String str3 = String.valueOf(i1);//调用的是形参int
System.out.println(str2);// 10
System.out.println(str3);// 10
Boolean bool = true;
System.out.println(String.valueOf(bool));//调用的是形参Object
}
String类型转成基本数据类型\包装类
- 通过包装类的
parseXXX()
方法转成基本数据类型\包装类。
举例
@Test
public void test5() {
// String类型转成基本数据类型\包装类
String str1 = "ABC";
String str2 = "123";
String str3 = "123.3";
String str4 = "True";
// 转成int
int i1 = Integer.parseInt(str2);// 123
// 转成float
float fl1 = Float.parseFloat(str3);// 123.3
Float fl2 = Float.parseFloat(str3);// 123.3
// 转成boolean
boolean bool1 = Boolean.parseBoolean(str4);// true
boolean bool2 = Boolean.parseBoolean(str1);// false
System.out.println(i1);
System.out.println(fl1);
System.out.println(fl2);
System.out.println(bool1);
System.out.println(bool2);
}
包装类面试题
面试题1
@Test
public void test1() {
Object o1 = true ? new Integer(1) : new Float(2.0f);
System.out.println(o1);//1.0
}
这个题的注意点,编译过程中三元运算符会提升类型,会将Integer
提升到Float
面试题2
@Test
public void test2() {
Object o1;
if (true) {
o1 = new Integer(1);
} else {
o1 = new Float(2.0f);
}
System.out.println(o1);//1
}
这个题无需考虑类型提升。
面试题3
@Test
public void test3() {
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println(i1 == i2);//false
Integer ii1 = 1;
Integer ii2 = 1;
System.out.println(ii1 == ii2);//true
Integer iii1 = 128;
Integer iii2 = 128;
System.out.println(iii1 == iii2);//false
}
- 第一个两个
Integer
对象都是通过构造出new
出来的,所以比较的是两个对象的内存地址。 - 第二个和第三个都是通过自动装箱实现的,那为什么结果不一样的?通过源码来看就明白了:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
Integer
里面有一个静态内部类IntegerCache
,是一个缓存类,将范围-128~127
的所有数字放进了cache[]
的静态数组(提高效率),如果通过自动装箱的方式发现数据是-128~127
的,就直接调用,无需new;-128~127
范围外的需要new出来。
练习题1
public class AchievementTest {
public static void main(String[] args) {
// 获取输入对象
Scanner scanner = new Scanner(System.in);
// 创建
Vector<Object> vector = new Vector<Object>();
// 成绩最大值
int max = 0;
// 遍历数据
// 输入负数截止
for (;;) {
// 判断输入是否为负数
System.out.print("请输入成绩:");
int data = scanner.nextInt();
if (data < 0) {
break;
} else if (data > 100) {
System.out.println("数据有误,请重新输!");
continue;
}
// 输入正确,获取最大值
if (max < data) {
max = data;
}
// 保存数据
// jdk5.0之前,不能存放基本数据类型,需要转成包装类,多态;jdk5.0之后可以存放,自动装箱
Integer in = data;
vector.addElement(in);
}
// 遍历比较
for (int i = 0; i < vector.size(); i++) {
// jdk5.0之前,不能存放基本数据类型,需要转成包装类;jdk5.0之后可以存放
Integer in = (Integer) vector.get(i);
int is = in;
int s = max - is;
if (s <= 10) {
System.out.println("成绩:" + in + ",优秀");
} else if (s <= 20) {
System.out.println("成绩:" + in + ",合格");
} else if (s <= 30) {
System.out.println("成绩:" + in + ",及格");
} else {
System.out.println("成绩:" + in + ",不及格");
}
}
}
}
本文由 Gorrywang 创作,严禁转载与复制!
最后编辑时间为: Aug 18,2016