第八章:面向对象编程中级
第八章:面向对象编程(中级)
IDEA基本设置
代码字体大小
菜单字体大小
idea颜色主题
idea文件编码设置(企业常用utf-8)
IDEA快捷键
1.删除当前行:Ctrl+d
2.复制当前行:Ctrl+alt+向下光标
3.补全代码:alt+/
4.添加注释/取消注释:Ctrl+/
5.导入该行需要的类,先配置auto import,然后使用alt+enter即可
6.快速格式化代码Ctrl+alt+L
7.快速运行程序alt+r
8.生成构造器、setter、getter等:alt+enter
9.查看一个类的层级关系:Ctrl+H
10.将光标放在一个方法上,输入Ctrl+B,可以定位到哪个类的方法
11.自动的分配变量名,通过在后面加.var
模板/自定义模板
file->settings->editor->Live templates->
查看有哪些模板快捷键/自己增加模板
main->主方法
sout->System.out.println("")
包
包的三大作用:
1.区分相同名字的类
2.类很多时,可以很好地管理类
3.控制访问范围!
基本语法:
package com.lczjava
1.package :关键字,表示打包
2.com.lczjava :表示包名
作用:
声明当前类所在的包,需要放在类的最上面,一个类中只能由一句package
import指令,位置放在package下面,在类定义前面,可以有多句且没有顺序要求。
包的本质分析:
实际上就是创建不同的文件夹来保存类文件
包的命名:
命名规则:
只能包含数字、字母、下划线、小圆点,但不能是数字开头,不能是关键字或保留字
命名规范:
一般是小写字母+小圆点
一般是com.公司名.项目名.业务模块名
如:com.sina.crm.user//用户模块
com.sina.crm.order//订单模块
com.sina.crm.utils//工具类
常用的包:
java.lang.*//lang包是基本包,含基本数据类型的封装,默认引入,无须手动引入
java.util.*//util包,系统提供的工具包,工具类,使用Scanner
Java.net.*//网络包,网络开发
java.awt.*//是做java的界面开发,GUI
引入包:
1.import java.util.*
2.import java.util.Scanner
注意:推荐使用第二种,清晰可见
访问修饰符
1.公开级别:public 都可以访问
2.受保护级别:protected 与默认级别相比,子类可以访问
3.默认级别:没有修饰符号 同类和同包可以访问,子类和不同包不可以访问
4.私有级别:private 只有同类可以访问,子类不能直接访问,但可以间接访问(公共方法)
注意事项:只有默认和public可修饰类,并且遵循上述访问权限的特点,即:
默认修饰,即只有同包可访问
public修饰,即都可以访问,同包不同包都可以
封装(encapsulation)
介绍:
封装就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作
封装的理解和好处
1):隐藏实现细节:方法(连接数据库)<--调用(传入参数...)
2):可以对数据增加业务逻辑进行验证,保证安全合理
封装的实现步骤(三步)
1):将属性进行私有化private[不能直接修改属性]
2):提供一个公共的(public)set方法,用于对属性判断并赋值
public void setXxx(类型 参数名){//Xxx表示某个属性
//加入数据验证的业务逻辑
属性 = 参数名
}
3):提供一个公共的(public)get方法,用于获取属性的值
public 数据类型 getXxx(){//可进行权限判断(如进行账号密码的登录),Xxx某个属性
return xx;
}
练习:
1.一个人名字,年龄,工资等隐私,要求不能随便查看人的年龄、工资等隐私,并对设置的年龄进和名字行合理的验证。
年龄合理就设置,否则给默认年龄,必须在1-120,name的长度在2-6字符之间
public class encapsulation {
public static void main(String[] args) {
People people = new People("safffffff",150,15000);
System.out.println(people.info());
}
}
class People {
public String name;
private int age;
private double salary;
public String getName() {
return name;
}
public People(String name, int age, double salary) {
setName(name);
this.name = getName();
setAge(age);
this.age = getAge();
this.salary = salary;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
} else {
System.out.println("您输入的名字不合法,默认值为:刘浩存");
this.name = "刘浩存";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {
this.age = age;
} else {
System.out.println("您输入的年龄有误,默认值为:18");
this.age = 18;
}
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String info(){
return "姓名:"+name + "年龄:" + age +"薪资:" + salary;
}
}
2.定义两个类:Account和AccountTest类
1.Account要求具有属性:姓名(长度为2或3或4位)、余额(必须大于20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值
2.通过setXxx的方法给Account的属性赋值
3.在AccountTest中测试
public class Account {
private String name;
private String pwd;
private double balance;
public Account(String name, String pwd, double balance) {
setName(name);
this.name = getName();
setPwd(pwd);
this.pwd = getPwd();
setBalance(balance);
this.balance = getBalance();
}
public String getName() {
return name;
}
public void setName(String name) {
if(name.length()>=2&&name.length()<=4) {
this.name = name;
}else{
System.out.println("您输入的名字不合法,默认值为:lhc");
this.name = "lhc";
}
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
if(pwd.length() == 6) {
this.pwd = pwd;
}else{
System.out.println("您输入的密码不合法,默认值为:123456");
this.pwd = "123456";
}
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
if(balance >= 20) {
this.balance = balance;
}else{
System.out.println("您输入的余额不合法,默认值为:20");
this.balance = 20.0;
}
}
public String info(){
return "姓名:" + name + " 密码:" + pwd + " 余额" + balance;
}
}
继承(inherit)
介绍:
便利:
1):代码复用性提高
2):代码扩展性和维护性提高:修改父类达到:一改全改
细节
1.子类继承了所有的属性和方法,但是私有属性不能在子类直接访问,要通过公有方法间接访问
2.子类必须调用父类的构造器,完成父类的初始化
3.创建子类对象时,子类构造器总会默认调用父类无参构造器,若父类没有无参构造器,则需用super指定调用父类的哪个有参构造器完成父类的初始化工作:super(参数列表)
4.super()和this()都只能放在构造器第一行,所以不能共存在一个构造器
5.super只能在构造器中使用且在第一句
6.父类构造器的调用不限于直接父类,将一直往上追溯直到Odject类
7.子类最多只能继承一个父类(直接继承),即java是单继承机制。
若想让A类继承B类和C类,可以让A继承B,让B继承C
继承内存布局和查找关系
查找关系:
(1):首先看子类是否有该属性
(2):如果子类有这个属性,并且可以访问,则返回信息
(3):如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息,若父类有但无法访问,则报错,cannot access)
(4):如果父类没有就按照(3)的规则,继续找上级父类,直到Object。
若最终没有找到,则提示方法不存在
练习
super关键字
基本介绍
super代表父类的引用,用于访问父类的属性、方法、构造器
基本语法
1.访问父类的属性,但不能访问父类的private属性
super.属性名
2.访问父类的方法,不能访问父类的private方法
super.方法名(参数列表)
3.访问父类的构造器:
super(参数列表);只放在构造器第一句
细节
1.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;
如果多个基类中都有同名的成员,使用super遵循就近原则
2.cal()等价于this.cal()//从子类开始查找cal()方法
super.cal()//从父类开始查找cal()方法
super和this的区别
方法重写
基本介绍
子类对父类方法进行重写:方法名称、返回类型、参数须都一样
注意事项和使用细节
1.子类的方法的参数、方法名称,要和父类方法的参数、方法名称完全一样
2.子类方法的返回类型和父类返回类型一样,或者是父类返回类型的子类
如:父类是Object,子类是String
3.子类方法不能缩小父类方法的访问权限
重载和重写区别
多态
基本介绍
方法或对象具有多种形态
方法多态
1.方法重载体现多态:传入不同的参数就会调用不同的sum方法
2.方法重写体现多态:不同的对象调用同一个say方法呈现不同结果
对象多态(核心、困难、重点)
1.一个对象的编译类型和运行类型可以不一致
2.编译类型在定义对象时,就确定了,不能改变。而且此时决定了该对象可以调用哪些方法
因为在编译阶段,能调用哪些成员,是由编译类型决定的
3.运行类型是可以变化的
4.编译类型看定义时 = 的左边,运行类型看 = 的右边
细节
多态的向上转型:
1.多态的前提:
(1):两个类存在继承关系
(2):存在向上转型
(3):存在方法重写
2.本质:父类的引用指向了子类的对象
3.语法:父类类型 引用名 = new 子类类型();
4.特点:(1):编译类型看左边,运行类型看右边
(2):可以调用父类中的所有成员(需遵守访问权限)
(3):不能调用子类中特有成员,可以调用子类中重写方法;
注:调用子类中特有成员,需要进行类对象的判断和向下转型
5.调用方法规则:调用方法时,按照从子类(运行类型)开始查找方法,若无,则去父类查找
多态的向下转型:
1.语法:子类类型 引用名 = (子类类型) 父类引用
2.只能强转父类的引用,不能强转父类的对象
3.要求父类的引用必须指向的是当前目标类型的对象
4.当向下转型后,可以调用子类类型中所有的成员
1.属性没有重写之说,属性的值看编译类型!
2.instanceOf比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型
练习
动态绑定机制
注释B类的sum和sum1()方法后,体现动态绑定机制
1.当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定
2.当调用对象属性时,没有动态绑定机制,哪里声明,那里使用
多态应用
多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
Shape [] shapes = new Shape [2];
shapes[0] = new Square(10.0);
shapes[1] = new Circle(5.0);
多态参数
方法定义的形参类型为父类类型,实参类型允许为子类类型
//上转型对象作为函数形参实现多态
public static void print(Shape t){
t.printArea();
}
//上转型对象进一步扩大范围作为函数形参实现多态,此时需进行类型判断和向下转型
public static void print1(Object t){
if(t instanceof Shape) {
((Shape) t).printArea();
}else{
System.out.println("类型有误");
}
}
Object类方法详解
equals方法
==和equals的对比(面试题)
1.==:既可以判断基本类型,又可以判断引用类型
2.==:如果判断基本类型,判断的是值是否相等
3.==:如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象
4.equals:是Object类中的方法,只能判断引用类型
5.默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等,如Integer、String
package Object;
public class equals {
public static void main(String[] args) {
//Integer类演示
Integer num1 = new Integer(1);
Integer num2 = new Integer(12);
Integer num3 = num1;
System.out.println(num1.equals(num2));
System.out.println(num1.equals(num3));
//String类演示
String s1 = new String("hello");
String s2 = new String("hello world");
String s3 = s1;
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
//自定义类Person演示(重写equals方法)
Person person = new Person("lun", 18, 'm');
Person person1 = new Person("lei", 18, 'm');
System.out.println(person1.equals(person));
}
}
class Person{
private String name;
private int age;
private char gender;
public Person(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public boolean equals(Object o){
Person person = (Person) o;
if(this.name == person.name && this.age == person.age &&this.gender == person.gender){
return true;
}
return false;
}
}
hashCode方法
返回对象的哈希码值。
实际上,由Object类定义的hashCode方法确实会针对不同的对象返回不同的整数(这一般是通过将该对象的内存地址转换称一个整数来实现的)
1):提高具有哈希结构的容器的效率
2):两个引用,如果指向的是同一个对象,则哈希值是一样的
3):两个引用,如果指向的是不同对象,则哈希值是不一样的
4):哈希值主要是根据地址号来的,不能完全等价于地址
toString方法
基本介绍
默认返回:全类名+@+哈希值的十六进制
子类往往重写toString方法,用于返回对象的属性信息
重写toString方法,打印对象或者拼接对象时,都会自动调用该对象的toString方法
finalize方法
1.当对象被回收时,系统自动调用该对象的finalize方法,子类可以重写该方法,做一些释放资源的操作
2.什么时候被回收:当某个对象没有任何引用时,则jvm就认为该对象是一个垃圾对象,就使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法
3.垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制
断点调试
快捷键
F7(跳入)
F8(跳过)
shift+F8(跳出)
F9(resume,执行到下一个断点)
零钱通系统
面向过程
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class smallChangeSys {
public static void main(String[] args) {
/*
化繁为简:功能:
(1):完成显示菜单,并可以选择
(2):完成零钱通明细
(3):完成收益入账
(4):完成消费
(5):退出
完善:
(6):循环接受输入,若为y则退出,若为n则不退出,若为其他则提示错误信息
(7):收益和消费金额进行校验,并给出错误提示
*/
//(1)完成显示菜单,并可以选择,loop为是否退出标志,choice为选择
Scanner scanner = new Scanner(System.in);
boolean loop = true;
int key;
//(2):完成零钱通明细:通过数组完成、通过对象完成、通过String拼接完成
String details = "------零钱通明细------";
//(3):完成收益入账:完成功能驱动程序员增加新的变化和代码
//增加新的变量
double money = 0;
double balance = 0;
Date date = null;//date 是 java.util.Date 类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");//可以用于日期格式化
//(4):完成消费
//定义新变量,保存消费的原因
String note = "";
//do-while循环,菜单至少显示一次
do{
System.out.println("\n======零钱通系统======");
System.out.println("\t\t1 零钱通明细");
System.out.println("\t\t2 收益入账");
System.out.println("\t\t3 消费");
System.out.println("\t\t4 退 出");
System.out.print("请选择(1-4):");
key = scanner.nextInt();
//使用switch 分支控制
switch(key){
case 1:
System.out.println(details);
break;
case 2:
System.out.print("收益入账金额:");
money = scanner.nextDouble();
//(7):money的值应该检验,待会儿完善
//编程思想(过关斩将):找出错误情况单独进行if单分支判断,而不是找正确情况进行多分支判断,可读性差
if(money <= 0){
System.out.println("收益的金额需要大于 0");
break;
}
balance += money;
date = new Date();//获取当前日期
//拼接收益入账信息到 details
details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t" + balance;
break;
case 3:
System.out.print("消费金额:");
money = scanner.nextDouble();
System.out.print("消费说明:");
note = scanner.next();
//(7):money的值应该检验,待会儿完善
if(money <= 0 || money > balance){
System.out.println("消费的金额小于0或者大于余额!");
break;
}
balance -= money;
date = new Date();//获取当前日期
//拼接收益入账信息到 details
details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;
break;
case 4://(6):循环接受输入,若为y则退出,若为n则不退出,若为其他则提示错误信息
// 1):定义一个变量choice,用来接受用户的输入
// 2):使用 while + break 处理接受的输入
// 3):退出 while 后,再判断choice是y还是n,就可以决定是否退出
// 4):将循环询问接受输入功能和退出系统功能进行拆分,
// 一段代码完成一个小功能,不要混在一起,降低耦合度
String choice = "";
while(true){//要求用户一直输入y/n,否则就一直循环
System.out.println("你确定要退出吗? y/n");
choice = scanner.next();
if("y".equals(choice) || "n".equals(choice)){
break;
}else{
System.out.println("您输入的有误,请重新输入!!!");
}
}
//判断choice是y还是n,决定是否退出
if(choice.equals("y")){
loop = false;
}
break;
default:
System.out.println("菜单选择有误,请重新输入");
}
}while(loop);
//(5):退出
if(!loop)
System.out.println("------退出了零钱通系统------");
}
}
面向对象
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/**
* 该类是完成零钱通的各个功能:
* (1):完成显示菜单,并可以选择
* (2):完成零钱通明细
* (3):完成收益入账
* (4):完成消费
* (5):退出
* 使用OOP(面向对象编程):可读性高,扩展性高,别人易调用
* 将各个功能对应一个方法
*/
public class smallChangeSysOOP {
//属性
//(1)完成显示菜单,并可以选择,loop为是否退出标志,choice为选择
Scanner scanner = new Scanner(System.in);
boolean loop = true;
int key;
//(2):完成零钱通明细:通过数组完成、通过对象完成、通过String拼接完成
String details = "------零钱通明细------";
//(3):完成收益入账:完成功能驱动程序员增加新的变化和代码
//增加新的变量
double money = 0;
double balance = 0;
Date date = null;//date 是 java.util.Date 类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");//可以用于日期格式化
//(4):完成消费
//定义新变量,保存消费的原因
String note = "";
//方法
public void mainMenu() {
do{
System.out.println("\n======零钱通系统(OOP)======");
System.out.println("\t\t1 零钱通明细");
System.out.println("\t\t2 收益入账");
System.out.println("\t\t3 消费");
System.out.println("\t\t4 退 出");
System.out.print("请选择(1-4):");
key = scanner.nextInt();
//使用switch 分支控制
switch(key){
case 1:
this.detail();
break;
case 2:
this.income();
break;
case 3:
this.pay();
break;
case 4:
this.exit();
break;
default:
System.out.println("菜单选择有误,请重新输入");
}
}while(loop);
}
public void detail() {
System.out.println(details);
}
public void income(){
System.out.print("收益入账金额:");
money = scanner.nextDouble();
//(7):money的值应该检验,待会儿完善
//编程思想(过关斩将):找出错误情况单独进行if单分支判断,而不是找正确情况进行多分支判断,可读性差
if(money <= 0){
System.out.println("收益的金额需要大于 0");
return;//break 换为 return,以不执行后面代码
}
balance += money;
date = new Date();//获取当前日期
//拼接收益入账信息到 details
details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t" + balance;
}
public void pay(){
System.out.print("消费金额:");
money = scanner.nextDouble();
System.out.print("消费说明:");
note = scanner.next();
//(7):money的值应该检验,待会儿完善
if(money <= 0 || money > balance){
System.out.println("消费的金额小于0或者大于余额!");
return;//break 换为 return
}
balance -= money;
date = new Date();//获取当前日期
//拼接收益入账信息到 details
details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;
}
public void exit(){
//(6):循环接受输入,若为y则退出,若为n则不退出,若为其他则提示错误信息
// 1):定义一个变量choice,用来接受用户的输入
// 2):使用 while + break 处理接受的输入
// 3):退出 while 后,再判断choice是y还是n,就可以决定是否退出
// 4):将循环询问接受输入功能和退出系统功能进行拆分,
// 一段代码完成一个小功能,不要混在一起,降低耦合度
String choice = "";
while(true){//要求用户一直输入y/n,否则就一直循环
System.out.println("你确定要退出吗? y/n");
choice = scanner.next();
if("y".equals(choice) || "n".equals(choice)){
break;
}else{
System.out.println("您输入的有误,请重新输入!!!");
}
}
//判断choice是y还是n,决定是否退出
if(choice.equals("y")){
loop = false;
System.out.println("------退出了零钱通系统------");
}
}
}
/**
* 直接调用smallChangeSysOOP 对象,显示主菜单即可
*/
public class smallChangeSysApp {
public static void main(String[] args) {
System.out.println("====hello公司====");
new smallChangeSysOOP().mainMenu();
}
}
本章作业
1.定义一个person类{name,age,job},初始化person对象数组,有3个person对象,并按照age从大到小进行排序,注:使用冒泡排序
package homework;
/**
* 定义一个person类{name,age,job}
* 初始化person对象数组,有3个person对象
*并按照age从大到小进行排序,注:使用冒泡排序
*/
public class Homework01 {
public static void main(String[] args) {
Person[] person = new Person[3];
person[0] = new Person("lcz",20,"大学生");
person[1] = new Person("lhc",21,"演员");
person[2] = new Person("漩涡鸣人",16,"火影");
System.out.println("====冒泡排序前====");
for (int i = 0; i < person.length; i++) {
System.out.println(person[i].getAge());
}
bubbleSort(person);
System.out.println("====冒泡排序后====");
for (int i = 0; i < person.length; i++) {
System.out.println(person[i].getAge());
}
}
//bubbleSort方法将Person数组根据年龄进行冒泡排序
public static void bubbleSort(Person[] person){
Person temp = new Person();
for(int i = 0;i < person.length;i++){
for(int j = 0;j < person.length-i-1;j++){
if(person[j].getAge() > person[j+1].getAge()){
temp = person[j];
person[j] = person[j+1];
person[j+1] = temp;
}
}
}
}
}
class Person{
private String name;
private int age;
private String job;
public Person(String name, int age, String job) {
this.name = name;
this.age = age;
this.job = job;
}
public Person() {
}
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;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
2.写出四种访问修饰符和各自的访问权限
package homework;
/**
* 写出四种访问修饰符和各自的访问权限
* public 同类、子类、同包、不同包都可访问
* 默认 同类、同包可访问,子类、不同包不可访问
* protected 同类、同包、子类可访问,不同包不可访问
* private 同类可访问,同包、不同包、子类都不可访问,注:子类可通过公共方法间接访问
*/
public class Homework02 {
}
3.==和equals的区别
package homework;
/**
* ==和equals区别
* 名称 概念 用于基本数据类型 用于引用类型
* == 比较运算符 比较值是否相等 比较地址是否相等
* equals Object对象的方法 不可以 可以,默认比较地址是否相等,但子类往往重写该方法,
* 用于比较属性是否相等,如(String,Integer)
*/
public class Homework03 {
}
4.什么是多态?多态的具体体现?
package homework;
/**
* 什么是多态?多态具体体现有哪些?
* 多态:方法或对象或接口的多种形态,是OOP的第三大特征,是建立在封装和继承的基础之上
* (1):方法多态:方法重载、方法重写
* (2):对象多态:条件:存在方法重写、存在上转型对象、有继承结构
* 编译类型和运行类型可以不一致:
* 编译类型编译时就确定,不可更改
* 运行类型可通过Object类的getClass()方法进行查看
* 编译类型看 = 左侧,运行类型看 = 右侧
* (3):接口多态:接口作为数据类型,不同实现该接口的类的对象的引用调用同一个接口的方法呈现出多种形态
*/
public class Homework04 {
}
5.什么是动态绑定机制?
package homework;
/**
* java的动态绑定机制是什么?
* 由多态引出的动态绑定机制:
* (1):当调用对象的方法时,该方法会和对象的内存地址/运行类型绑定
* (2):当调用对象的属性时,没有动态绑定机制,哪里声明,那里使用
*/
public class Homework05 {
}
a
package homework;
/**
- ==和equals区别
- 名称 概念 用于基本数据类型 用于引用类型
- == 比较运算符 比较值是否相等 比较地址是否相等
- equals Object对象的方法 不可以 可以,默认比较地址是否相等,但子类往往重写该方法,
-
用于比较属性是否相等,如(String,Integer)
*/
public class Homework03 {
}
#### 4.什么是多态?多态的具体体现?
```java
package homework;
/**
* 什么是多态?多态具体体现有哪些?
* 多态:方法或对象或接口的多种形态,是OOP的第三大特征,是建立在封装和继承的基础之上
* (1):方法多态:方法重载、方法重写
* (2):对象多态:条件:存在方法重写、存在上转型对象、有继承结构
* 编译类型和运行类型可以不一致:
* 编译类型编译时就确定,不可更改
* 运行类型可通过Object类的getClass()方法进行查看
* 编译类型看 = 左侧,运行类型看 = 右侧
* (3):接口多态:接口作为数据类型,不同实现该接口的类的对象的引用调用同一个接口的方法呈现出多种形态
*/
public class Homework04 {
}
5.什么是动态绑定机制?
package homework;
/**
* java的动态绑定机制是什么?
* 由多态引出的动态绑定机制:
* (1):当调用对象的方法时,该方法会和对象的内存地址/运行类型绑定
* (2):当调用对象的属性时,没有动态绑定机制,哪里声明,那里使用
*/
public class Homework05 {
}