Object类
概述
java.lang.Object 类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类(包括数组)都可以使用。在对象实例化的时候,最终找的父类就是Object。如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:
public class MyClass /*extends Object*/ {
// ...
}
根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。在学习Object类的方法前,我们先回顾下
== :运算符
可以使用在基本数据类型变量和引用数据类型变量中,用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错。
- 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)只要两个变量的值相等,即为true。
- 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体。只有指向同一个对象时,==才返回true
Object类中的主要结构
Object类中定义的方法如下
equals方法
- public boolean equals(Object obj) :指示其他某个对象是否与此对象“相等”。所有类都继承了Object,也就获得了equals()方法。equals是一个方法,而非运算符,只能适用于引用数据类型。查看Ojbect类在的源码
public boolean equals(Object obj) {
return (this == obj);
}
我们可以知道以下信息
/*
参数:
Object obj:可以传递任意的对象
== 比较运算符,返回的是一个布尔值 true false
基本数据类型:比较的是值
引用数据类型:比价的是两个对象的地址值
this是谁?那个对象调用的方法,方法中的this就是那个对象;p1调用的equals方法所以this就是p1
obj是谁?传递过来的参数p2
this==obj -->p1==p2
*/
结论:
- Objec类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体 如果没有覆盖重写equals方法,那么Object类中默认进行 == 运算符的对象地址比较,只要不是同一个对象,结果必然为false。Object类的equals方法,默认比较的是两个对象的地址值,没有意义,所以我们要重写equals方法,比较两个对象的属性。
对象内容比较
- 如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。
重写equals()方法的原则
- 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是 “true”。
- 自反性:x.equals(x)必须返回是“true”。
- 传递性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”, 那么z.equals(x)也应该返回是“true”。
- 一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
任何情况下,x.equals(null),永远返回是“false”; x.equals(和x不同类型的对象)永远返回是“false”。例如:我们重写自定义类Person的equals方法,代码如下
package demo01;
import java.util.Objects;
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
// 如果对象地址一样,则认为相同
if (this == o) return true;
// 如果参数为空,或者类型信息不一样,则认为不同
if (o == null || getClass() != o.getClass()) return false;
// 转换为当前类型
Person person = (Person) o;
// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
return age == person.age && Objects.equals(name, person.name);
}
//其他代码
}
这段代码充分考虑了对象为空、类型一致等问题,但方法内容并不唯一。大多数IDE都可以自动生成equals方法的代码内容。在IntelliJ IDEA中,可以使用 Code 菜单中的 Generate… 选项,也可以使用快捷键 alt+insert ,并选择 equals() and hashCode() 进行自动代码生成。如下图所示:
toString() 方法
- toString()方法在Object类中定义,其返回值是String类型,返回类名和它 的引用地址。 在进行String与其它类型数据的连接操作时,自动调用toString()方法。
Date now=new Date();
System.out.println(“now=”+now);
//相当于
System.out.println(“now=”+now.toString());
- 直接打印对象的名字,其实就是调用对象的toString方法
- 看一个类是否重写了toString,直接打印这个类的对象即可,如果没有重写toString方法那么打印的是对象的对象的类型+@+内存地址值。
由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。
覆盖重写
如果不希望使用toString方法的默认行为,则可以对它进行覆盖重写。例如自定义的Person类:
public class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//其他代码
}
在IntelliJ IDEA中,可以点击 Code 菜单中的 Generate... ,也可以使用快捷键 alt+insert ,点击 toString() 选项。选择需要包含的成员变量并确定。如下图所示:
finalize方法
程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定。垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。
其他的方法以后在学习....
包装类(Wrapper)
Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类,基本数据类型有了类的特点,就可以调用类中的方法,Java才是真正的面向对象。
基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:
- 装箱:从基本类型转换为对应的包装类对象。
- 拆箱:从包装类对象转换为对应的基本类型。
用Integer与 int为例:
- 基本数值---->包装对象
Integer i = new Integer(4);//使用构造函数函数
Integer iii = Integer.valueOf(4);//使用包装类中的valueOf方法
- 包装对象---->基本数值
int num = i.intValue();
动装箱与自动拆箱
由于我们经常要做基本类型与包装类之间的转换,从Java 5(JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:
Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5; 加法运算完成后,再次装箱,把基本数值转成对象。
字符串转换成基本数据类型。
- 通过包装类的构造器实现:
int i = new Integer(“12”);
- 通过包装类的parseXxx(String s)静态方法:
Float f = Float.parseFloat(“12.1”);
注意:
- 如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出 java.lang.NumberFormatException异常。
基本数据类型转换成字符串
- 调用字符串重载的valueOf()方法:
String fstr = String.valueOf(2.34f);
- 更直接的方式:
总结:基本类型、包装类与String类间的转换
软件测试
查询百度百科:软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出之间的审核或者比较过程。软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。
测试的分类
- 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。
- 白盒测试:需要写代码的。关注程序具体的执行流程。Junit测试属于白盒测试中的一种。
现在我们拿到一个需求,需要测试一下Junit包下的Calculator类代码编写是否正确。代码如下
package Junit;
/**
* 计算器类
*/
public class Calculator {
/**
* 加法
* @param a
* @param b
* @return
*/
public int add(int a, int b){
return a +b;
}
/**
*
* @param a
* @param b
* @return
*/
public int sub(int a,int b){
return a -b;
}
}
照以前的知识,我们需要在测试类中,创建Calculator类的对象,在调用Calculator类中编写的方法,查看方法的运行结果和我们期望的结果一样。但是这么做很多的缺点:如果我们要测试多个方法,必须把前面测试好的代码注释掉,以免造成影响。步骤麻烦等等。下面我们就是要在IDEA开发工具中使用Junit单元测试的知识来测试这个类。
步骤如下
1:创建一个包,存放测试用例。包名建议以.text结尾,并且与要测试的代码存放的包平级。
2:在MyTest包中,创建类(测试用例)。建议类名以Test结尾
3:在测试用例中定义测试方法,建议为test要测试的方法名称,例如要测试add方法,测试方法名称可以为testAdd()。测试方法建议空参和void返回值。
4:给测试方法加@Test注解,导入junit依赖环境
代码完成之后,方法代码如下
package MyTest;
import org.junit.Test;
public class CalculatorTest {
/**
* 测试add方法
*/
@Test
public void testAdd(){
}
}
5:在测试用例中,创建对象,调用要测试的方法进行测试
package MyTest;
import Junit.Calculator;
import org.junit.Test;
public class CalculatorTest {
/**
* 测试add方法
*/
@Test
public void testAdd(){
//创建对象
Calculator c = new Calculator();
//调用方法
int result = c.add(1, 3);
}
}
6:使用会使用断言操作来处理结果, Assert.assertEquals(期望的结果,运算的结果);
package MyTest;
import Junit.Calculator;
import org.junit.Assert;
import org.junit.Test;
public class CalculatorTest {
/**
* 测试add方法
*/
@Test
public void testAdd(){
//创建对象
Calculator c = new Calculator();
//调用方法
int result = c.add(1, 3);
//断言操作
Assert.assertEquals(4,result);
}
}
7:查看下面,如果是绿色的则代码要测试的内容没有问题,红色则说明代码有错误
常用的注解
@Before
- 修饰的方法会在测试方法之前被自动执行
@After
- 修饰的方法会在测试方法执行之后自动被执行
代码举例
package MyTest;
import Junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class CalculatorTest {
/**
* 初始化方法:
* 用于资源申请,所有测试方法在执行之前都会先执行该方法
*/
@Before
public void init() {
System.out.println("init...");
}
/**
* 释放资源方法:
* 在所有测试方法执行完后,都会自动执行该方法
*/
@After
public void close() {
System.out.println("close...");
}
/**
* 测试add方法
*/
@Test
public void testAdd() {
//1.创建计算器对象
System.out.println("testAdd...");
Calculator c = new Calculator();
//2.调用add方法
int result = c.add(1, 2);
//System.out.println(result);
//3.断言 我断言这个结果是3
Assert.assertEquals(3, result);
}
@Test
public void testSub() {
//1.创建计算器对象
Calculator c = new Calculator();
int result = c.sub(1, 2);
System.out.println("testSub....");
Assert.assertEquals(-1, result);
}
}
代码执行之后的代码