Java学习笔记七(面向对象特征之多态)

多态性:

多态性的理解:可以理解为一个事物的多种形态;
何为多态:父类的引用指向子类的对象;
多态的使用:(虚拟方法调用)
有了对象的多态性之后,我们在编译期只能调用父类中声明的方法,但在运行期,实际执行的是子类重写父类的方法
总结:编译看左边,运行看右边。
多态性使用的前提:①类的继承关系②方法的重写
注意:对象的多态性只使用于方法,不适用于属性(也就是说属性是编译运行都看右边)

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.earnMoney();
		
		//*************************************************
		System.out.println("*******************");
		//对象的多态性:父类的引用指向子类的对象
		Person p2 = new Man();
//		Person p3 = new Woman();
		//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
		p2.eat();//男人多吃肉,长肌肉
		p2.walk();//男人霸气的走路
		
//		p2.earnMoney();
		
		System.out.println(p2.id);//1001
		
	}
}
//多态性的使用举例一:
public class AnimalTest {
	
	public static void main(String[] args) {
		
		AnimalTest test = new AnimalTest();
		test.func(new Dog());
		
		
		test.func(new Cat());
	}
	
	public void func(Animal animal){//Animal animal = new Dog();
		animal.eat();
		animal.shout();
		
		if(animal instanceof Dog){
			Dog d = (Dog)animal;
			d.watchDoor();
		}
	}
	
//	public void func(Dog dog){
//		dog.eat();
//		dog.shout();
//	}
//	public void func(Cat cat){
//		cat.eat();
//		cat.shout();
//	}
}


class Animal{
	
	
	public void eat(){
		System.out.println("动物:进食");
	}
	
	public void shout(){
		System.out.println("动物:叫");
	}
	
	
}

class Dog extends Animal{
	public void eat(){
		System.out.println("狗吃骨头");
	}
	
	public void shout(){
		System.out.println("汪!汪!汪!");
	}
	
	public void watchDoor(){
		System.out.println("看门");
	}
}
class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
	
	public void shout(){
		System.out.println("喵!喵!喵!");
	}
}

//举例二:

class Order{
	
	public void method(Object obj){
		
	}
}

//举例三:
class Driver{
	
	public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
		//规范的步骤去操作数据
//		conn.method1();
//		conn.method2();
//		conn.method3();
		
	}
	
}

面试题:多态是编译时行为还是运行时行为?
程序证明如下:(运行时行为)

//证明如下:
class Animal  {
 
	protected void eat() {
		System.out.println("animal eat food");
	}
}

class Cat  extends Animal  {
 
	protected void eat() {
		System.out.println("cat eat fish");
	}
}

class Dog  extends Animal  {
 
	public void eat() {
		System.out.println("Dog eat bone");

	}

}

class Sheep  extends Animal  {
 

	public void eat() {
		System.out.println("Sheep eat grass");

	}

 
}

public class InterviewTest {

	public static Animal  getInstance(int key) {
		switch (key) {
		case 0:
			return new Cat ();
		case 1:
			return new Dog ();
		default:
			return new Sheep ();
		}

	}

	public static void main(String[] args) {
		int key = new Random().nextInt(3);

		System.out.println(key);

		Animal  animal = getInstance(key);
		
		animal.eat();
		 
	}

}

Object类:

java.lang.Object类是所有类的根父类;如果在类的声明中没有使用extends表明其父类,则默认java.lang.Objece为其父类;Object类中的功能(属性和方法)具有通用性。
Object类中无属性;
Object类中的方法包括:equals()、toString()、getClass()、hashCode()、clone()、finalize()、wait()、notify()、notifyAll();
并且在Object类中值声明了一个空参的构造器。

面试题final、finally、finalize的区别:
待添加。

public class ObjectTest {

	public static void main(String[] args) {
		
		Order order = new Order();
		System.out.println(order.getClass());//class com.atguigu.java1.Order
		//System.out.println(order.getClass().getSuperclass());//class java.lang.Object

	}
}

class Order{
	
}

Object类的clone()的使用:

public class CloneTest {
	public static void main(String[] args) {
		Animal a1 = new Animal("花花");
		try {
			Animal a2 = (Animal) a1.clone();
			System.out.println("原始对象:" + a1);
			//原始对象:Animal [name=花花]
			a2.setName("毛毛");
			System.out.println("clone之后的对象:" + a2);
			//clone之后的对象:Animal [name=毛毛]
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
}

class Animal implements Cloneable{
	private String name;

	public Animal() {
		super();
	}

	public Animal(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Animal [name=" + name + "]";
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	
}

Object类中的toString()方法:

当我们输出一个对象的引用是,实际调用的就是当前对象的toString()方法;
Object类中toString()的定义:
public String toStrong(){
return getClass().getName() + ‘@’ + Inteager.toHexString(hashCode());
}
像String、Date、File、包装类等都重写了Object类中的toSring方法,使得在调用对象的toString方法是返回“实体内容”。

public class ToStringTest {
	public static void main(String[] args) {
		
		Customer cust1 = new Customer("Tom",21);
		System.out.println(cust1.toString());//com.atguigu.java1.Customer@15db9742-->Customer[name = Tom,age = 21]
		System.out.println(cust1);//com.atguigu.java1.Customer@15db9742-->Customer[name = Tom,age = 21]
		
		String str = new String("MM");
		System.out.println(str);//MM
		
		Date date = new Date(4534534534543L);
		System.out.println(date.toString());//Mon Sep 11 08:55:34 GMT+08:00 2113
		
	}
}

Finalize的使用:

public class FinalizeTest {
	public static void main(String[] args) {
		Person p = new Person("Peter", 12);
		System.out.println(p);
		p = null;//此时对象实体就是垃圾对象,等待被回收。但时间不确定。
		System.gc();//强制性释放空间
	}
}

class Person{
	private String name;
	private int age;

	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;
	}
	//子类重写此方法,可在释放对象前进行某些操作
	@Override
	protected void finalize() throws Throwable {
		System.out.println("对象被释放--->" + this);
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

面试题: == 和 equals() 区别:

一、回顾 == 的使用
== :运算符
1、可以使用在基本数据类型变量和引用数据类型变量中
2、 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
补充: == 符号使用时,必须保证符号左右两边的变量类型一致。

二、equals()方法的使用:
1、是一个方法,而非运算符
2、只能适用于引用数据类型
3、 Object类中equals()的定义:
public boolean equals(Object object){
return (object == this);
}

说明: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("****************************");
		System.out.println(cust1.equals(cust2));//false--->true
		System.out.println(str1.equals(str2));//true
		
		Date date1 = new Date(32432525324L);
		Date date2 = new Date(32432525324L);
		System.out.println(date1.equals(date2));//true
		
		
	}
}
//自动生成的equals()
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Customer other = (Customer) 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;
	}
	
	
	
	//重写的原则:比较两个对象的实体内容(即:name和age)是否相同
	//手动实现equals()的重写
//	@Override
	public boolean equals(Object obj) {
	
	System.out.println("Customer equals()....");
		if (this == obj) {
            return true;
        }
		
		if(obj instanceof Customer){
			Customer cust = (Customer)obj;
			//比较两个对象的每个属性是否都相同
			if(this.age == cust.age && this.name.equals(cust.name)){
				return true;
			}else{
			return false;
		}
			
			//或
			return this.age == cust.age && this.name.equals(cust.name);
		}else{
			return false;
		
		}		
	}

单元测试:

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.如果执行结果出现异常:红条

@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();
	}

包装类的使用:

java提供了八种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征;
要求掌握:
基本数据类型、包装类和String三者之间的相互转换;

public class MyWrapperTest {
	@Test
	// String -> 基本数据类型,引用数据类型
	public void test5() {
		String str = "123";
		int num1 = Integer.parseInt(str);
		System.out.println(num1);
		
		boolean flag = Boolean.parseBoolean(str);
		System.out.println(flag);
	}
	
	@Test
	// 基本数据类型、引用数据类型 -> String
	public void test4() {
		//方式一:
		int num2 = 98;
		String str2 = num2 + "";
		System.out.println(str2);
		
		//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
		//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在
		//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率
		
		Integer in1 = 56;
		System.out.println(in1);
		String str3 = in1 +"";
		System.out.println(str3);
		//方式二
		int num3 = 78;
		String str4 = String.valueOf(num3);
		
		
		String str5 = String.valueOf(in1);
		System.out.println(str5);
	}
	@Test
	// 基本数据类型和引用数据类型之间的互换
	public void test3() {
		// 自动装箱和自动拆箱
		int num = 12;
		Integer in = num;
		System.out.println(in);
		
		Integer in1 = 98;
		int num1 = in1;
		System.out.println(num1);
	}
	

}

关于包装类使用的面试题

public class InterviewTest {

	@Test
	public void test1() {
		//如果表达式为true,则执行表达式1。
		  //如果表达式为false,则执行表达式2。
		  //表达式1 和表达式2要求是一致的。
		Object o1 = true ? new Integer(1) : new Double(2.0);
		System.out.println(o1);// 1.0

	}

	@Test
	public void test2() {
		Object o2;
		if (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内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
		//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在
		//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率
		
		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
	}

}
发布了11 篇原创文章 · 获赞 14 · 访问量 5453

猜你喜欢

转载自blog.csdn.net/ssnszds/article/details/104514201
今日推荐