Java_多态

Posted 小企鹅推雪球!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java_多态相关的知识,希望对你有一定的参考价值。

Java_多态

Java_多态的概念

  1. 多态是同一个行为具有多个不同表现形式或者形态的能力,举个例子,人都要上洗手间,但是有专门为男人准备的,也有为女人准备的
  2. 多态就是同一个接口,使用不同的实例而执行不同操作

多态的优点:消除类型之间的耦合关系,可替换性,可扩充性,多态使得继承使用更加灵活

多态存在的必要条件:

  1. 继承,重写,父类引用指向子类对象Parent p = new Child();
    对象的多态性就是指:父类的引用指向子类的对象

Java_使用多态时的注意事项

  1. 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
  2. 多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
  3. 多态性可以直接应用在抽象类和接口上
  4. Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定,简称:编译时,看左边;运行时,看右边。
  5. 若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
  6. 多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法)
  7. 多态情况下,“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
public class Test {
    public static void main(String[] args) {
      show(new Cat());  // 以 Cat 对象调用 show 方法
      show(new Dog());  // 以 Dog 对象调用 show 方法
 
      Animal a = new Cat();  // 向上转型 
      a.eat();               // 调用的是 Cat 的 eat
      Cat c = (Cat)a;        // 向下转型 
      c.work();        // 调用的是 Cat 的 work
  } 
 
    public static void show(Animal a)  {
      a.eat(); 
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情
            Cat c = (Cat)a; 
            c.work(); 
        } else if (a instanceof Dog) { // 狗做的事情
            Dog c = (Dog)a; 
            c.work(); 
        } 
    } 
}
 
abstract class Animal { 
    abstract void eat(); 
} 
 
class Cat extends Animal { 
    public void eat() { 
        System.out.println("吃鱼"); 
    } 
    public void work() { 
        System.out.println("抓老鼠"); 
    } 
} 
 
class Dog extends Animal { 
    public void eat() { 
        System.out.println("吃骨头"); 
    } 
    public void work() { 
        System.out.println("看家"); 
    } 
}

Java_对象的多态性

  1. 对象的多态 :在Java中,子类的对象可以替代父类的对象使用
  2. 一个变量只能有一种确定的数据类型
  3. 一个引用类型变量可能指向(引用)多种不同类型的对象
Person p = new Student();
Object o = new Person();//Object类型的变量o,指向Person类型的对象
o = new Student(); //Object类型的变量o,指向Student类型的对

子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)。

一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法

	Student m = new Student();
	m.school = “pku”; //合法,Student类有school成员变量
	Person e = new Student(); 
	e.school = “pku”; //非法,Person类没有school成员变量

属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。

多态的实例

  1. 方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法
public class Test {
	public void method(Person e) {
		e.getInfo();
	}
	public static void main(Stirng args[]) {
		Test t = new Test();
		Student m = new Student();
		t.method(m); // 子类的对象m传送给父类类型的参数e
	}
}

Java_虚拟方法调用(Virtual Method Invocation)

正常的方法调用

	Person e = new Person();
	e.getInfo();
	Student e = new Student();
	e.getInfo();

虚拟方法调用(多态情况下)

	Person e = new Student();
	e.getInfo(); //调用Student类的getInfo()方法

虚函数(虚拟方法)的概念

  1. 虚函数(虚拟方法)的存在是为了多态。
  2. 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,
  3. 父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
  4. Java 中其实没有虚函数的概念,它的普通函数就相当于C++的虚函数,动态绑定是Java的默认行为。
  5. 如果 Java 中不希望某个函数具有虚函数特性,可以加上final关键字变成非虚函数。

编译时类型和运行时类型

	Person e = new Student();
	e.getInfo(); //调用Student类的getInfo()方法
  1. 编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。

Java_多态总结

  1. 多态的作用:提高了代码的通用性,常称作接口重用
  2. 多态的前提:需要存在继承或者实现关系,有方法的重写
  3. 编译时:要查看引用变量所声明的类中是否有所调用的方法。
  4. 运行时:调用实际new的对象所属的类中的重写方法。
  5. 成员变量:不具备多态性,只看引用变量所声明的类

Java_子类继承父类

继承成员变量和继承方法的区别

package com.company;

// 继承成员变量和继承方法的区别
public class Java_JiCheng_01 {
    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(); // 10
    }
}


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); // 20
    }
}

  1. 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。
  2. 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,子类中的实例变量依然不可能覆盖父类中定义的实例变量

Java_instanceof 操作符

  1. x instanceof A:检验x是否为类A的对象,返回值为boolean型。 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
  2. x instanceof A: 如果x属于类A的子类B,x instanceof A值也为true。

Java_对象类型转换 (Casting )

基本数据类型的Casting:

  1. 自动类型转换:小的数据类型可以自动转换成大的数据类型,如long g=20; double d=12.0f
  2. 强制类型转换:可以把大的数据类型强制转换(casting)成小的数据类型,如 float f=(float)12.0; int a=(int)1200L

对Java对象的强制类型转换称为造型

  1. 从子类到父类的类型转换可以自动进行
  2. 从父类到子类的类型转换必须通过造型(强制类型转换)实现
  3. 无继承关系的引用类型间的转换是非法的
  4. 在造型前可以使用instanceof操作符测试一个对象的类型

对象类型转换实例一

public class ConversionTest {
	public static void main(String[] args) {
		double d = 13.4;
		long l = (long) d;
		System.out.println(l);
		int in = 5;
		// boolean b = (boolean)in;
		Object obj = "Hello";
		String objStr = (String) obj;
		System.out.println(objStr);
		Object objPri = new Integer(5);
		// 所以下面代码运行时引发ClassCastException异常
		String str = (String) objPri;
	}
}

对象类型转换实例二

public class Test {
	public void method(Person e) { // 设Person类中没有getschool() 方法
	// System.out.pritnln(e.getschool()); //非法,编译时错误
	if (e instanceof Student) {
		Student me = (Student) e; // 将e强制转换为Student类型
		System.out.pritnln(me.getschool());
		}
	}
	public static void main(String[] args){
		Test t = new Test();
		Student m = new Student();
		t.method(m);
	}
}

Java_Object 类

  1. Object类是所有Java类的根父类,如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
  2. public class Person等价于:public class Person extends Object

Java_== 和equals 方法

==操作符

  1. ==:基本类型比较值:只要两个变量的值相等,即为trueint a=5; if(a==6){…}
  2. 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才返回true
Person p1=new Person();
Person p2=new Person();
if (p1==p2){}
  1. “==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错

equals方法

  1. equals():所有类都继承了Object,也就获得了equals()方法。还可以重写。
  2. 只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象。格式:obj1.equals(obj2)
  3. 特例:当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;原因是:在File、String、Date及包装类(Wrapper Class)类中重写了Object类的equals()方法。
  4. 当自定义使用equals()时,可以重写。用于比较两个对象的“内容”是否都相等

Java_重写equals()方法的原则

  1. 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”
  2. 自反性:x.equals(x)必须返回是“true”
  3. 传递性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”
  4. 一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”
  5. 任何情况下,x.equals(null),永远返回是“false”x.equals(和x不同类型的对象)永远返回是“false”

Java_==操作符和equals的区别

  1. == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
  2. equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
  3. 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。

Java_toString()方法

  1. toString()方法在Object类中定义,其返回值是String类型,返回类名和它的引用地址。
  2. toString()方法在Object类中定义,其返回值是String类型,返回类名和它
    的引用地址。
	Date now=new Date();
	System.out.println(“now=+now); 相当于
	System.out.println(“now=+now.toString());
  1. 可以根据需要在用户自定义类型中重写toString()方法
	如String 类重写了toString()方法,返回字符串的值。
	s1=“hello”;
	System.out.println(s1);//相当于System.out.println(s1.toString());
  1. 基本类型数据转换为String类型时,调用了对应包装类的toString()方法int a=10; System.out.println(“a=”+a)

Java_包装类(Wrapper)的使用

  1. Java针对八种基本数据类型定义相应的引用类型—包装类(封装类)
  2. 有了类的特点,就可以调用类中的方法,Java才是真正的面向对象

基本数据类型包装成包装类的实例 —装箱

  1. 装箱通过包装类的构造器实现:int i = 500; Integer t = new Integer(i);
  2. 装箱:还可以通过字符串参数构造包装类对象:Float f = new Float(“4.56”);long l = new Long(“asdf”); //NumberFormatException

获得包装类对象中包装的基本类型变量 —拆箱

  1. 调用包装类的.xxxValue()方法:boolean b = bObj.booleanValue();

JDK1.5之后,支持自动装箱,自动拆箱。但类型必须匹配

字符串转换成基本数据类型:

  1. 通过包装类的构造器实现:int i = new Integer(“12”)
  2. 通过包装类的parseXxx(String s)静态方法Float f = Float.parseFloat(“12.1”);

基本数据类型转换成字符串

  1. 调用字符串重载的valueOf()方法:String fstr = String.valueOf(2.34f);
  2. 自动转换:String intStr = 5 + ""

Java_包装类实例

装箱:包装类使得一个基本数据类型的数据变成了类。有了类的特点,可以调用类中的方法。

String s = t.toString(); // s = “500“,t是类,有toString方法
String s1 = Integer.toString(314); // s1= “314“ 将数字转换成字符串。
String s2=4.56;
double ds=Double.parseDouble(s2); //将字符串转换成数字

拆箱:将数字包装类中内容变为基本数据类型。

int j = t.intValue(); // j = 500,intValue取出包装类中的数据

// 包装类在实际开发中用的最多的在于字符串变为基本数据类型。
String str1 = "30" ;
String str2 = "30.3" ;
int x = Integer.parseInt(str1) ; // 将字符串变为int型
float f = Float.parseFloat(str2) ; // 将字符串变为int型

以上是关于Java_多态的主要内容,如果未能解决你的问题,请参考以下文章

No2_1.接口继承多态_Java学习笔记_接口

15_Java筑基之Object类多态

15_Java筑基之Object类多态

Java_多态

阶段1 语言基础+高级_1-3-Java语言高级_02-继承与多态_第2节 抽象类_9_接口的私有方法定义

java_第4章 继承与多态_第4周编程题_将MP3媒体类型存放进Database