java2_day07 java常用类之Objects类和包装类
作者:互联网
Java常用类之Object类、包装类
目录
-
Object类的使用
-
单元测试方法的使用
-
包装类的使用
1 Object类的使用
-
object类包含以下几个方法
-
hashcode() 集合里边有讲
-
toString()
-
clone() 用的较少
-
getClass() 获取当前对象的类,反射讲
-
notify() 多线程里讲
-
wait() 多线程里讲
-
equals()
-
-
Object类是所有Java类的根父类
-
如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
-
public class Person{
}
等价于
-
public class Person extends Object{
}
-
-
例:method(Object obj){...} //可以接收任何类作为其参数
Person o = new Person();
method(o);
-
程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行回收依然不确定。
-
对象回收之前会先调用finalize方法
面试题:final、finally、finalize的区别?
-
前两个是关键字,finalize是方法,一般不要主动调用。
1.1 Object中equals()方法
面试题:==和equals的区别
package com.xin.java;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/28 11:24
* Description:
* 面试题: == 和 equals()的区别
* 一、 ==运算符:
* 1. 可以使用在基本数据类型变量和引用数据类型的变量中
* 2. 如果比较的是基本数据类型变量,比较两个变量保存的数据是否相等。(不一定类型要相同)
* 如果比较的是引用数据类型变量,比较两个对象的地址值是否相同。即两个引用是否指向同一个对象实体。
*二、 equals()方法的使用
* 1. 是一个方法,而非运算符
* 2. 只能适用于引用数据类型,(像类才能用点后面加方法的方式)。
* 3. Object中equals()的定义:
* public boolean equals(Object obj) {
* return this == obj;
* }
* 说明: Object类中定义的equals()和==作用是相同的,比较两个对象的地址值是否相同。
* 4. 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,
* 比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
* 5. 通常情况下,我们自定义的类如果使用equals()的话,也是比较两个对象的实体内容是否相同,那么
* 我们就需要对Object类中的equals()方法进行重写。
*/
public class EqualsTest {
public static void main(String[] args) {
int i =10;
int j = 10;
double d = 10.0;
System.out.println(i == j); //TRUE
System.out.println(i == d); //TRUE,数值相等就行,和类型无关
boolean b = true;
// System.out.println(i == b); //不能和布尔型比较,编译报错
char c = 10;
System.out.println(i == c); //TRUE
char c1 = 'A';
char c2 = 65;
System.out.println(c1 == c2); //TRUE
Customer cust1 = new Customer("Tom", 21);
Customer cust2 = new Customer("Tom", 21);
System.out.println(cust1 == cust2); //false,地址值不同
String str1 = new String("atguigu");
String str2 = new String("atguigu");
System.out.println(str1 == str2); //false,地址值不同
System.out.println("===============================");
//equals()方法测试
System.out.println(cust1.equals(cust2)); //false ,看底层,用的是object里边的equals()方法, 里边用的也是==
//重写了customer类之后,结果为true
System.out.println(str1.equals(str2)); //TRUE,用的是String里边的equals()方法,String里边进行了重写
}
}
Customer类如下:
package com.xin.java;
import java.util.Objects;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/28 11:57
* Description:
*/
public class Customer {
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
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;
}
//重写的原则,比较两个对象的实体内容(即name和age)是否相同
// @Override
// public boolean equals(Object obj) {
// return super.equals(obj);
// }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Customer customer = (Customer) o;
return age == customer.age && //省略了this
Objects.equals(name, customer.name); //name已经是String字符串了,所以直接可以用equals了
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Customer[name = " + name + ", age = " + age + " ]";
}
}
-
重写equals()方法的原则
-
对称性:如果x.equals(y)返回是“true” ,那么y.equals(x)也应该返回是“true
-
自反性: x.equas(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”
-
练习题1:
package com.xin.java;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 9:48
* Description:
* equals()练习1:
* 编写Order类,有int型的orderId, String型的orderName,
* 相应的getter( )和setter( )方法,两个参数的构造器,
* 重写父类的equals( )方法: public boolean equals(Object obi ).
* 并判断测试类中创建的两个对象是否相等。
*/
public class OrderTest {
public static void main(String[] args) {
Order order1 = new Order(1001, "AA");
Order order2 = new Order(1001, "BB");
Order order3 = new Order(1001, new String("BB"));
//如果重写equals时,name不用equals方法的时候,很可能会出错,因为这里是通过new的方式建立的字符串
System.out.println(order1.equals(order2)); //false
System.out.println(order3.equals(order2)); //true
}
}
//Order类也可以新建一个文件
class Order{
private int orderId;
private String 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;
}
public Order(int orderId, String orderName) {
this.orderId = orderId;
this.orderName = orderName;
}
@Override
public boolean equals(Object obj) {
if(this == obj){ //如果地址相同,那就不用比了
return true;
}
if(obj instanceof Order){ //看是不是Order类
Order order = (Order) obj;
//如果是,进行一下强转,向下转型,这样才能使用点方法获得属性,从而进行内容的比较
// return this.orderId == order.orderId && this.orderName == order.orderName; //这是错误的
return this.orderId == order.orderId && this.orderName.equals(order.orderName);
}
return false;
}
}
练习题2:
-
请根据以下代码自行定义能满足需要的MyDate类, 在MyDate类中覆盖equals方法,使其判断当两个MyDate类型对象的年月日都相同时,结果为true,否则为false。 public boolean equals(Object O)
package com.xin.java;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 10:13
* Description:
*/
public class MyDateTest {
public static void main(String[] args) {
MyDate m1 = new MyDate(14, 3, 1976);
MyDate m2 = new MyDate(14, 3, 1976);
if(m1 == m2){
System.out.println("m1 == m2");
}else{
System.out.println("m1 != m2"); //bingo
}
if(m1.equals(m2)){
System.out.println("m1 is equal to m2"); //bingo
}else{
System.out.println("m1 is not equal to m2");
}
}
}
class MyDate{
private int day;
private int month;
private int year;
public MyDate(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof MyDate){
MyDate myDate = (MyDate) obj;
return this.year == myDate.year && this.month == myDate.month && this.day == myDate.day;
}
return false;
}
}
1.2 toString()方法
-
toString()方法在Object类中定义,其返回值是String类型,返回类名和它的引用地址。
-
在进行String与其它类型数据的连接操作时,自动调用toString()方法 Date now=new Date(); System.out.printn("now="+now);相当于 System.out.printin("now="+now.toString();
-
可以根据需要在用户自定义类型中重写toString(方法),如String类重写了toString()方法,返回字符串的值。 s1="hello"; System.out.printin(s1)//相当于System.out.printin(s1.toString();
-
基本类型数据转换为String类型时,调用了对应包装类的toString()方法
-
int a=10; system.out.printn("a="+a);
-
package com.xin.java;
import java.sql.SQLOutput;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 10:32
* Description:
* Object中toString()的使用
* 1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
* 2. Object类中toString()的定义:
* public String toString() {
* return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
* }
* 3. 像String、Date、File、包装类等都重写了Object类中的toString()方法
* 使得在调用对象的toString()时,返回"实体内容"信息。
* 4. 自定义类也可以重写toString()方法,当调用此方法时,返回对象的实体内容。
*/
public class toStringTest {
public static void main(String[] args) {
Customer cust1 = new Customer("Tom", 21);
System.out.println(cust1.toString()); //com.xin.java.Customer@27e0e4,输出类名和引用地址
System.out.println(cust1); //结果是一样的,com.xin.java.Customer@27e0e4
//重写之后,输出Customer[name = Tom, age = 21 ]
String mm = new String("MM");
System.out.println(mm); //输出MM,因为String类中进行了重写
}
}
1.3 Object类综合练习
-
几何类GeometricObject通用属性定义:
package com.xin.java1;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 11:25
* Description:
*/
public class GeometricObject {
protected String color;
protected double weight;
public GeometricObject() { //空参构造器要求初始化
this.color = "white";
this.weight = 1.0;
}
public GeometricObject(String color, double weight) {
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
-
对于GeometricObject子类Circle的要求如下:
package com.xin.java1;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 11:39
* Description:
*/
public class Circle extends GeometricObject { //子类
private double radius;
public Circle() {
super(); //已经继承了父类的属性
radius = 1.0;
// color = "white";
// weight = 1.0;
}
public Circle(double radius) {
this.radius = radius;
}
public Circle(String color, double weight, double radius) {
super(color, weight);
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double findArea(){ //求圆的面积
return 3.14 * radius * radius;
}
@Override //判断圆的半径是否相等,相等返回true,重写equals()方法
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof Circle){
Circle circle = (Circle) obj;
return this.radius == circle.radius;
}
return false;
}
@Override
public String toString() {
return "Circle{" +
"radius=" + radius +
'}';
}
}
-
测试方法:
package com.xin.java1;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 15:30
* Description:
*/
public class CircleTest {
public static void main(String[] args) {
Circle circle = new Circle(2.0);
Circle circle2 = new Circle(3.0);
System.out.println("颜色是否相等" + circle.color.equals(circle2.color)); //颜色是否相等true
// System.out.println(circle.color); //white
// System.out.println(circle.getColor()); //white
System.out.println("半径是否相等" + (circle.getRadius() == circle2.getRadius())); //半径是基本数据类型,不用equals
System.out.println("圆1的半径为:" + circle.toString()); //圆1的半径为:Circle{radius=2.0}
System.out.println("圆2的半径为:" + circle2.toString()); //圆2的半径为:Circle{radius=3.0}
}
}
2 单元测试方法的使用
package com.xin.java1;
import org.junit.Test;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 15:51
* Description:
* Java中的JUnit单元测试
* 单元测试方法的使用:
* 1. 步骤:
* 自己打出@Test,导入即可。
* 2. 创建Java类,进行单元测试。
* 此时的Java要求 1. 此类是public的 2. 此类提供公共的无参的构造器
* 3. 此类中声明单元测试方法
* 此时的单元测试方法,方法的权限是public,没有返回值,没有形参
* 4. 此单元测试方法上需要声明注释:@Test
* 5. 声明好单元测试方法以后,就可以在方法体内测试相关内容
*/
public class JUnitTest {
@Test
public void testEquals(){
}
}
3 包装类的使用
-
针对八种基本数据类型定义相应的引用类型——包装类(封装类)
-
有了类的特点,就可以调用类中的方法,Java才是真正的面向对象
3.1 基本类型、包装类与String类间的转换
3.2 基本数据类型与包装类之间的转换
package com.xin.java2;
import org.junit.Test;
import java.io.InputStreamReader;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 16:48
* Description:
* 包装类的使用:
* 1. java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
* 2. 掌握: 基本数据类型、包装类、String三者之间的相互转换
*/
public class WrapperTest {
/*
JDK 5.0新特性,自动装箱与自动拆箱
*/
@Test
public void test3(){
int num1 = 10;
// method(。。) //此时需要包装类了,需要进行转换
//自动装箱:基本数据类型-->包装类
int num2 = 10;
Integer in1 = num2; //基本数据类型直接赋值给包装类的对象了,而不用新建对象
boolean b1 = true;
Boolean b2 = b1;
//自动拆箱:包装类-->基本数据类型
System.out.println(in1.toString()); //in1是一个对象,可以用。方法
int num3 = in1; //可以直接把对象对应的值给基本数据类型
}
public void method(Object obj){
}
//包装类-->基本数据类型: 调用包装类的xxxValue()
//需求:有时需要用基本数据类型进行加减运算,包装类做不到
@Test
public void test2(){
Integer in1 = new Integer(12);
int i1 = in1.intValue(); //转换为基本类型
System.out.println(i1 + 1); //13
Float f1 = new Float(12.3f);
float f2 = f1.floatValue(); //转换为基本类型
System.out.println(f2 + 1); //13.3
}
//基本数据类型-->包装类: 调用包装类的构造器
//需求:转换为包装类才能调用相关的方法
@Test
public void test1(){
int num1 = 10;
Integer in1 = new Integer(num1); //Integer重写了toString方法了
System.out.println(in1.toString()); //10
Integer in2 = new Integer("123");
System.out.println(in2.toString()); //可以是纯粹数值的字符串,123
Float f1 = new Float(12.3f);
Float f2 = new Float("12.3f");
System.out.println(f1.toString()); //12.3
System.out.println(f2); //12.3
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean("true");
Boolean b3 = new Boolean("true123");
//其他类型的这样混写会报异常,可以查看源码
System.out.println(b1);
System.out.println(b2);
System.out.println(b3); //FALSE
Order order = new Order();
System.out.println(order.isMale); //FALSE,默认值
System.out.println(order.isFemale); //NULL,是个类了,不是基本数据类型了
}
}
class Order{
boolean isMale;
Boolean isFemale;
}
3.3 基本数据类型包装类与String类之间的转换
-
因为基本数据类型与包装类可以实现自动拆箱和装箱了,暂且把他们看作一个整体。
//String类-->基本数据类型、包装类 :调用包装类的parseXxx()
@Test
public void test5(){
String str1 = "123";
//错误的情况
// int num1 = (int)str1;
// Integer num1 = (Integer)str1; //有子父类的关系才能进行强转
int num2 = Integer.parseInt(str1);
System.out.println(num2 + 1); //124
String str2 = "true";
Boolean.parseBoolean(str2); //true
}
//基本数据类型、包装类-->String类 :调用String重载的valueOf(Xxx xxx)
@Test
public void test4(){
int num1 = 10;
//方式1:连接运算
String str1 = num1 + "";
System.out.println(str1); //输出为10,但是是字符串型的"10"
//方式2.
float f1 = 12.3f; //基本数据类型转换为String
String str2 = String.valueOf(f1); //输出为12.3,但是是字符串型的"12.3"
Double d1 = new Double(12.4);
String str3 = String.valueOf(d1); //包装类转换为String,和基本数据类型与String之间的转换是一致的。
System.out.println(str3);
}
3.4 包装类的面试题
package com.xin.java2;
import org.junit.Test;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 20:17
* Description:
*/
public class InterniewTest {
@Test
public void test1(){
Object o1 = true ? new Integer(1) : new Double(2.0);
//编译的时候,就进行了数据提升,把int型变成了double,所以是1.0
System.out.println(o1); //1.0
}
@Test
public void test2(){
Object o2;
if(true) //直接里边是true了,直接运行
o2 = new Integer(1);
else
o2 = new Double(2.0);
System.out.println(o2); //1
}
@Test
public void test3(){
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); //false
Integer m = 1;
Integer n = 1; //用的自动装箱
System.out.println(m == n); //true
//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[]数组,保存了从-128~127范围的整数。
//如果我们使用自动装箱的方式,给Integer赋值的范围在-128~127范围内时,可以直接使用数组中的元素,不用再去new了。
Integer x = 128; //自动装箱预先定义好了-128~127数组,当用128,只能新建
Integer y = 128;
System.out.println(x = y); //false
}
}
3.5 包装类的课后练习
package com.xin.java2;
import com.sun.jdi.PathSearchingVirtualMachine;
import org.junit.Test;
import java.util.Scanner;
import java.util.Vector;
/**
* Created with IntelliJ IDEA.
* User: xinxueqi
* Date: 2022/4/29 21:06
* Description:
* 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。
* 提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。
* 而向量类java.util.Vector可以根据需要动态伸缩。
* 创建Vector对象: Vector v=new Vector() ;
* 给向量添加元素: v.addElement(Object obi); / /obj必须是对象
* 取出向量中的元素: object
* obj=v.elementAt(0);
* 注意第一个元素的下标是0,返回值是Object类型的。
* 计算向量的长度: v.size();
* 若与最高分相差10分内: A等; 20分内: B等;30分内: C等;其它: D等
*/
public class ScoreTest {
public static void main(String[] args) { //使用test没运行起来
System.out.println("请输入学生成绩:");
Scanner scanner = new Scanner(System.in); //从键盘读取成绩
Vector vector = new Vector(); //创建Vector对象,相当于原来的数组
while (scanner.hasNextInt()) { //添加进数组
int score = scanner.nextInt();
//int型转换为包装类
Integer in1 = score; //自动装箱
vector.addElement(in1);
}
//找出最高分
int max = (Integer) vector.elementAt(0); //强转同时,使用自动拆箱
for (int i = 1; i < vector.size(); i++) {
int a = (Integer) vector.elementAt(i);//强转同时,使用自动拆箱
if (max <= a) {
max = a;
}
}
// System.out.println("student 0 score is i grade is ");
for (int i = 0; i < vector.size(); i++) { //输出成绩
int b = (Integer) vector.elementAt(i);
String c = level(b, max);
System.out.println("student " + i + " score is " + b + " , " + " grade is " + c);
}
}
public static String level(int score, int max){ //方法,String为返回值属性,里边为形参
if(score <= max && score >= max - 10){
return "A";
}else if(score < max - 10 && score >= max - 20){
return "B";
}else if(score < max - 20 && score >= max - 30){
return "C";
}else {
return "D";
}
}
}
改进:
-
输入时,要规定啥时候停止break,同时出现非法输入,重新输入,使用continue;
-
可以进行循环嵌套,应该可以简化代码
4 复习
-
存在子父类之间的关系才能进行强转,强转指向下转型,这样就可以获得子类的属性和方法。
-
多态性
-
可以理解为一个事物的多种形态
-
向上转型:多态
-
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用).
-
举例:
-
Person p = new Man(); //此时还是只有父类的方法,但是如果此时子类对于父类方法进行了重写,就按照子类的进行输出。(详看之前的笔记)
-
Object obj = new Date();
-
-
-
谈谈对多态性的理解?
-
实现代码的通用性
-
Object中定义的public boolean equals(Object obj){},使用equals()的时候,就可以只要是obj子类都可以。
-
抽象类和接口的使用体现了多态性。(抽象类、接口不能实例化)只能通过子类new,这样的话通过多态性,就能使用equals()。
-
-
多态是运行时行为,取一个随机数,编译根本看不出来,只能运行之后才能知道。(要看之前对于多态的讲解了)
-
数组也作为Object的子类出现,可以调用Object类中声明的方法。
标签:java,String,day07,System,equals,Objects,println,public,out 来源: https://www.cnblogs.com/xinxueqi/p/16210627.html