Java-day13(instanceof 、object类的使用、Wrapper、equals、JUnit、toString )

instanceof

例一:
person类:

package com.acoffee.exer3;

public class Person {
	String name;
	int age;
	
	public void eat() {
		System.out.println("人:吃饭");
	}
	
	public void walk() {
		System.out.println("人:走路");
	}
}

Man类:

package com.acoffee.exer3;

public class Man extends Person{
	boolean isSmoking;
	
	public void earnMonry() {
		System.out.println("男人负责挣钱养家");
	}
	
	public void eat() {
		System.out.println("男人多吃肉,长肌肉");
	}
	
	public void walk() {
		System.out.println("男人要霸气的走路");
	}
}

Woman类:

package com.acoffee.exer3;

public class Woman extends Person {
	boolean isBeauty;
	
	public void goShopping() {
		System.out.println("女人喜欢购物");
	}
	
	public void eat() {
		System.out.println("女人少吃要减肥");
	}
	
	public void walk() {
		System.out.println("女人秀气的走路");
	}
}

PersonTest类:

package com.acoffee.exer3;


public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person();
		p1.eat();
		
		Man man = new Man();
		man.eat();
		man.age = 25;
		man.earnMonry();
		
		//************************
		//对象的多态性:我们声明的是父类 调
		//用的是子类的对象。即父类的对象指
		//向子类的对象
		Person p2 = new Man();
		Person p3 = new Woman();
		//多态的使用:当调用子父类同名参数的方法是,实际
		//执行的是子类重写父类的方法---虚拟方法调用
		p2.eat();
		p2.walk();
		//p2.earnMoney(); 不能调用子类所特有的方法:编译时:p2是Person类型    
		
	}
}

有了对象的多态性以后,内存实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的方法不能调用。
我们昨天讲的不能调用子类所特有的方法,但是这种情况应该怎么解决呢?
向下转型:使用强制类型转换符: Man m1 = (man)p2;

Man m1 = (Man)p2;
m1.earnMoney();
m1.isSmoking = true;

这样操作过后我们就可以调用子类锁特有的属性和方法。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用强转时,可能会报ClassCastException这个类转换异常 因为我们先转换成了Man类型然后在转换成Woman类型不能的所以报了异常,为了我们写程序时去避免这个问题我们就引入关键字instanceof

instanceof 关键字的使用:

要求x所属的类与类A必须是子类和父类(直接或间接)的关系,否则编译错误。

a(变量名) instance of A(类):
判断对象a是否是类A的实例。如果是,返回true:如果不是,返回false。

使用情景:为了避免向下转型是出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就向下转型。如果返回false,不进行向下转型。

如果B是A的父类:
a instance of A返回true, 那么a instance of B也返回true.

我们修改PersonTest类:

package com.acoffee.exer3;

public class PersonTest {
	public static void main(String[] args) {
			
		Person p2 = new Man();

		if(p2 instanceof Woman) {
			Woman w1 = (Woman)p2;
			w1.goShopping();
			System.out.println("*******Woman*******");
		}
		if(p2 instanceof Man) {
			Man w2 = (Man)p2;
			w2.earnMoney();
			System.out.println("*******Man*******");
		}
	}
}

执行结果:
在这里插入图片描述

我们发现if(p2 instanceof Man){ }中的代码是执行了的,而if(p2 instanceof Woman){ }中的代码却没有执行,因为我们只Person p2 = new Man();所以if(p2 instanceof Man){ }就能通过,而woman那个就不能通过所以就运行不出来.

在这里插入图片描述
应该去new一个叫低级别的类 然后在往上转型。

多态练习:

练习一:

class Base {
	int count = 10;

	public void display() {
		System.out.println(this.count);
	}
}

class Sub extends Base {
	int count = 20;

	public void display() {
		System.out.println(this.count);
	}
}

public class FieldMethodTest {
	public static void main(String[] args) {
		Sub s = new Sub();
		System.out.println(s.count);//20
		s.display();//20
		
		Base b = s;//多态性
		//==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否相同
		System.out.println(b == s);//true
		System.out.println(b.count);//10
		b.display();//20
	}
}

  • 1.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中:编译看左边,运行看右边

  • 2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量:编译运行都看左边。

练习二:
在这里插入图片描述

/*
 * 建立InstanceTest 类,在类中定义方法method(Person e);
		在method中:
		(1)根据e的类型调用相应类的getInfo()方法。
		(2)根据e的类型执行:
		如果e为Person类的对象,输出:
		“a person”;
		如果e为Student类的对象,输出:
		“a student”
		“a person ” 
		如果e为Graduate类的对象,输出: 
		“a graduated student”
		“a student”
		“a person” 

 * 
 * 
 * 
 */
public class InstanceTest {
	
	public static void main(String[] args) {
		
		InstanceTest test = new InstanceTest();
		test.method(new Student());
	}
	
	
	public void method(Person e){
		
		//虚拟方法调用
		String info = e.getInfo();
		System.out.println(info);
		
		//方式一
//		if(e instanceof Graduate){
//			System.out.println("a graduated student");
//			System.out.println("a student");
//			System.out.println("a person");
//		}else if(e instanceof Student){
//			System.out.println("a student");
//			System.out.println("a person");
//		}else{
//			System.out.println("a person");
//		}
		
		//方式二
		if(e instanceof Graduate){
			System.out.println("a graduated student");
		}
		
		if(e instanceof Student){
			System.out.println("a student");
		}
		
		if(e instanceof Person){
			System.out.println("a person");
		}
		
		
	}
}

class Person {
	protected String name = "person";
	protected int age = 50;

	public String getInfo() {
		return "Name: " + name + "\n" + "age: " + age;
	}
}

class Student extends Person {
	protected String school = "pku";

	public String getInfo() {
		return "Name: " + name + "\nage: " + age + "\nschool: " + school;
	}
}

class Graduate extends Student {
	public String major = "IT";

	public String getInfo() {
		return "Name: " + name + "\nage: " + age + "\nschool: " + school + "\nmajor:" + major;
	}
}

object类的使用

在这里插入图片描述
Object类中的功能(属性,方法)具有的通用性。
属性:无
方法:equals()/ toString()/ getClass/ hashCode()/ clone()/ finalize()/ wait()/ notify()/ notifyAll()

Object类之声明一个空参构造器

我们下面重点讲equals方法 和 toString方法。

equals

== 和 equals 的区别

一、回顾 == 的使用
==:运算符
1.可以使用在基本数据类型变量和引用数据类型变量中。

2.如果比较的是基本数据变量:比较两个变量保存的数据是否相等。(不一定类型要相等)在这里插入图片描述
3.如果是比较的是引用数据类型变量,比较的是两个地址值是否相同,即两个引用是否指向同一个对象实体。
在这里插入图片描述

二、equals方法的使用
1.是一个方法,而非运算符
2. 只能适用于引用数据类型
3. Object类中equals()的定义:

public boolean equals(Object obj){
	return (this == obj);
}

说明:在Object类中定义的equals()和 == 的作用是相同的。

4.像String、Data、File、包装类等都重写了Object() 方法。重写以后,比较的不是两个引用的地址是否相同,而是比较的两个对象的“实体内容”是否相同。

举例:

在这里插入图片描述
5.通常情况下,我们自定义的类如果使用equals的话,也通常是比较两个对象的“实体内容”是否相同。那么我们就需要对Object类中的equals()进行重写。 可以自动生成。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
补充: == 符号使用时, 必须保证付哈左右两边的变量类型保持一致。

练习:
在这里插入图片描述

package com.acoffee.exer;
/*
 * 编写Order类,有int型的orderId,String型的orderName,
 * 相应的 getter()和setter()方法,
 * 两个参数的构造器,重写父类的equals()方法: 
 * public boolean equals(Object obj),
 * 并判断测试类中创建的两个对象是否相等。
*/
public class OrderTest {
	public static void main(String[] args) {
		Order order1 = new Order(1001,"AA");
		Order order2 = new Order(1001,"BB");
		
		System.out.println(order1.equals(order2));
		
		Order order3 = new Order(1001,"BB");
		System.out.println(order2.equals(order3));
	}
	
}

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) {
		super();
		this.orderId = orderId;
		this.orderName = orderName;
	}
	@Override
		public boolean equals(Object obj) { //先判断引用地址一不一样 
			if(this == obj) {				//引用地址一样直接返回true
				return true;
			}
			if(obj instanceof Order) {//然后判断这个形参跟我们被判断这个对象
									  //是不是同一类型,如果类型都不同就返回false,如
									  //一个String型的去判断,而这个形参不是String类型
									  //两个就肯定不相同
				Order order = (Order)obj; //我们把形参强转
				
				return this.orderId == order.orderId && //orderId是int型,我们直接用==比较
						 this.orderName.equals(order.orderName);//而orderName是String类型我们直接用equals比较
														//我们前面提到equals在String中是已经被重写了
			}
			return false;
		}
	
}

toString()

在这里插入图片描述

Java中的JUnit单元测试

  • 步骤:
  • 1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步
  • 2.创建Java类,进行单元测试。
  • 此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器
  • 3.此类中声明单元测试方法。
  • 此时的单元测试方法:方法的权限是public,没有返回值,没有形参
  • 4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test;
  • 5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。
  • 6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
  • 说明:
  • 1.如果执行结果没有任何异常:绿条
  • 2.如果执行结果出现异常:红条
public class JUnitTest {
	
	int num = 10;
	
	@Test
	public void testEquals(){
		String s1 = "MM";
		String s2 = "MM";
		System.out.println(s1.equals(s2));
		//ClassCastException的异常
//		Object obj = new String("GG");
//		Date date = (Date)obj;
		
		System.out.println(num);
		show();
	}
	
	public void show(){
		num = 20;
		System.out.println("show()....");
	}
	
	@Test
	public void testToString(){
		String s2 = "MM";
		System.out.println(s2.toString());
	}
}

包装类的使用(Wrapper)

在这里插入图片描述
在这里插入图片描述
练习:
基本数据类型→包装类

package com.acoffee.java1;

import org.junit.Test;

	public class WrapperTest {
	//基本数据类型→包装类:调用包装类的构造器
	@Test
	public void test1() {
		
		int num1 = 10;
		//这种表达方式是错误的num1是基本数据类型不能去调方法
//		System.out.println(num1.toString());

		Integer in1 = new Integer(num1);
		System.out.println(in1.toString());
		
		Integer in2 = new Integer("123");
		System.out.println(in2.toString());
		
		//报异常
//		Integer in3 = new Integer("123abc");不是整形
//		System.out.println(in3.toString());
		
		Float f1 = new Float(12.3f);
		Float f2 = new Float("12.3");
		System.out.println(f1);
		System.out.println(f2);
		
		//boolean型 忽略大小写只要是true就输出true,不然就是flase
		Boolean b1 = new Boolean("true");
		Boolean b2 = new Boolean("TrUe");
		System.out.println(b2);//true
		Boolean b3 = new Boolean("123abc");
		System.out.println(b3);//false
		
		Order order = new Order();
		System.out.println(order.isMale);//false
		//因为现在isFemale是一个类了
		System.out.println(order.isFemale);//null
	}
}

class Order{
	boolean isMale;
	Boolean isFemale;
}


包装类→基本数据类型:调用包装类的xxxValue()

package com.acoffee.java1;

import org.junit.Test;


public class WrapperTest2 {
	//包装类→基本数据类型:调用包装类的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.3);
		float f2 = f1.floatValue();
		System.out.println(f2 + 1);//13.3
	}
	
}

自动拆箱、自动装箱

	//JDK5.0新特性:自动装箱 与自动拆箱
	@Test
	public void test3() {
		//int num1 = 10;
		//基本数据类型→包装类的对象
		//method(num1);
		
		//自动装箱:基本数据类型→包装类
		int num2 = 10;
		Integer in1 = num2;//自动装箱
		
		boolean b1 = true;
		Boolean b2 = b1;//自动装箱
		
		//自动拆箱:包装类→基本数据类型
		System.out.println(in1.toString());
		
		int num3 = in1;//自动拆箱
	}
	
	public void method(Object obj) {
		System.out.println(obj);
	}

基本数据类型、包装类→String类型:调用String常在的valueof(xxx xxx)

package com.acoffee.java1;

import org.junit.Test;
public class wrapperTest3 {	
		//基本数据类型、包装类→String类型:调用String常在的valueof(xxx xxx)
		@Test
		public void test4() {
			
			int num1 = 10;
			//方式一:连接运算
			String str1 = num1 + "";
			System.out.println(str1);//"10"
			
			//方式二:调用String.valueOf(xxx xxx)
			int num2 = 20;
			String str2 = String.valueOf(num2);
			System.out.println(str2);//"20"
			
			float num3 = 12.3f;
			String str3 = String.valueOf(num3);
			System.out.println(num3);//"12.3"
			
			Double d1 = new Double(12.4);
			String str4 = String.valueOf(d1);
			System.out.println(d1);//"12.4"
		}
	}

//String类型→基本数据类型、包装型:调用包装类xxxx.parsexxx(String s)

package com.acoffee.java1;

import org.junit.Test;

public class WrapperTest4 {
	//String类型→基本数据类型、包装型:调用包装类xxxx.parsexxx(String s)
	@Test
	public void test4() {
		String str1 = "123";
		int num1 = Integer.parseInt(str1);
		System.out.println(num1 + 1);//124
		
		String str2  = "true1";
		boolean b1 = Boolean.parseBoolean(str2);
		System.out.println(b1);//false
	}
}

练习题:

面试题:

package com.acoffee.java1;

import org.junit.Test;

public class WrapperTest5 {

	@Test
	public void test1() {
		Object o1 = true ? new Integer(1) : new Double(2.0); 
		System.out.println(o1);//1.0	因为这里会将所有代码都运行
								//一遍所以当运行到Double(2.0)时,前面的int就会类型自动提升为Double型.
	}
	
	@Test
	public void test2() {
		Object o2;
		if(true) {
			o2 = new Integer(1);
		}else {
			o2 = new Double(2.0);
		}
		System.out.println(o2);//1
	}
	
}

面试题2:

@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 x = 128;//相当于new了一个Integer对象
		Integer y = 128;//相当于new了一个Integer对象
		System.out.println(x == y);//false
	}

原因:
Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],保存了从-128 到 127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率。

综合练习:
在这里插入图片描述

public class ScoreTest {
	public static void main(String[] args) {
	//1.实例化Scanner,用于从键盘获取学生成绩
	Scanner scan = new Scanner(System.in);
	
	//2.创建Vector对象,Vector v=new Vector();相当于原来的数组
	Vector v=new Vector();
	
	//3.通过for(;;)或while(true)方式,给Vecotr中添加数组
	int maxScore = 0;
	for(;;) {
		System.out.print("请输入你要读入的成绩(以输入负数表示结束):");
		int score = scan.nextInt();
		
		//3.2 当输入时负数时,跳出循环
		if(score < 0) {
			break;
		}
		if(score > 100) {
			System.out.println("输入错误,请重新输入");
			continue;
		}
		
		//3.1 添加操作:v.addElement(Object obj);
		//JDK5.0之前:(自动装箱)
//		Integer inScore = new Integer(score);
//		v.addElement(inScore);
		
		v.addElement(score);//自动装箱
		
		//4.获取成绩的最大值
		if(score > maxScore) {
			maxScore = score;
		}
	}
	
	//5.遍历Vector,得到每个学生的成绩,并与最大成绩比较,得到每个学生的成绩。
	char level;
	for(int i = 0;i < v.size();i++) {
		Object  obj = v.elementAt(i);
		
		//在JDK5.0之前:
//		Integer inScore = (Integer)obj;
//		int score = inScore.intValue();
		int score = (Integer)obj;
		
		if(maxScore - 10 < score ) {
			level = 'A';
		}else if(maxScore - 20 < score ){
			level = 'B';
		}else if(maxScore - 30 < score ){
			level = 'C';
		}else {
			level = 'D';
		}
		System.out.println("student - " + i + "score is "+ score+",level is   "+level);
		}
	}
}

每日一练:

1.如何实现向下转型?需要注意什么问题?如何解决此问题?

Person p = new Man();
使用强转符:()
Man m = (Man)p;

可能ClassCastException异常。

使用instanceof在进行向下转型前判断。
if(p instanceof Man){
Man m = (Man)p;
}

2.== 和 equals()有何区别?

在这里插入图片描述

3.重写equals

class User{
String name;
int age;
	//重写其equals()方法
	public boolean equals(Object obj){
		if(obj == this){
			return true;
		}
		if(obj instanceof User){
			User u = (User)obj;
			return this.age == u.age && this.name.equals(u.name);
		}
		return false;
	}
}

4. 写出8种基本数据类型及其对应的包装类

int Integer
char Character

5. 基本数据类型、包装类与String三者之间如何转换

自动装箱、自动拆箱

Integer i = 10;

基本数据类型、包装类—>String: valueOf(Xxx xx)
String—>基本数据类型、包装类:parseXxx(String s)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值