Java学习日记基础(五)——类、对象之this、静态变量(类变量)、静态方法(类方法)、四大特征
this
赵本山问奥尼尔:“我的爸爸的爸爸是谁?”
奥尼尔:“不知道”
赵本山:“你傻啊,是我爷爷”
奥尼尔回去问科比:“我的爸爸的爸爸是谁?”
科比:“不知道”
奥尼尔:”你傻啊,是赵本山的爷爷“
就像这个笑话一样,不同的人,用this时,指向的对象也是变的。
普通方法中,this总是指向调用该方法的对象
//this在成员方法中的用处 //this就是指代当前对象,是一个隐式参数 public class thissss { public static void main(String []args) { Student s1 = new Student(); s1.name = "小白"; s1.age = 17; s1.study(); System.out.println(s1.name); Student s2 = new Student(); s2.name = "小徐"; s2.age = 18; s2.study(); } } class Student { int age; String name; public void study() //在创建成员方法(函数)的时候会自动传一个this参数,指向该对象的地址,但是是隐藏的 { this.name = "小黑"; //s1.name = "小黑"; //这条语句是错误的,因为对象要在类创建完成之后才有 //但是使用this.name就可以给类进行赋值 //因为this指向创建的对象的地址,所以this.name就会找到该对象中study()方法的地址 //对这个地址进行操纵,总而更改当前对象的值 System.out.println(name+"在学习"); } }
图解:
构造方法中,this总是指向正要初始化的对象
//this在构造方法中的用处 //用来指向正在初始化的对象 public class thissss2 { public static void main(String []args) { Student s1 = new Student(17); System.out.println(s1.age); Student s2 = new Student(18); } } class Student { int age; String name; public Student(int age) { //age = age //直接写age指代的是public void Student(String name,int age)传进来的name,就近原则 //this.age指代的是当前正在初始化的对象中的String age; this.age = age; } } 输出结果: age = age时,输出的是0,并非是正常的结果 this.age = age时,输出的是正常的结果17
原因也是因为会默认传一个this参数,用来指向当前使用这条命令的对象的地址,这样就可以正确的初始化当前对象中成员变量的值了
注意:this不能用于static方法(学了static方法就知道为什么了)
变量的种类
实例变量、类变量、常量都是属于成员变量的,成员变量又被称为全局变量
public class A{ String id; //实例变量 private String Tel; //实例变量 private int size; //实例变量 private static String depart; //类变量 final String design="样式"; //常量 } /*其中实例变量、类变量、常量都是属于成员变量的,成员变量又被称为全局变量, 成员变量的范围比实例变量更宽泛 */
方法(函数)的种类
实例方法(instance method):或叫成员方法(member method)。供实例用的方法,必须要先有实例,才能通过此实例调用实例方法。
静态变量 / 类变量
提问:有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在有多少人在玩呢?请使用面向对象的思想,编程解决。
1 public class Demo1 2 { 3 public static void main(String []args) 4 { 5 int total = 0; 6 Child ch1 = new child(3,"小徐"); 7 ch1.joinGame(); 8 total++; 9 10 Child ch2 = new child(4,"小白"); 11 ch2.joinGame(); 12 total++; 13 //查看总人数的时候,只需要输入total的值就可以了 14 //但是要求是使用面向对象的方法,课时这个total并没有封装到对象中去 15 } 16 } 17 18 //定义kid类 19 class Child 20 { 21 int age; 22 String name; 23 public Child(int age,String name) 24 { 25 this.age = age; 26 this.name = name; 27 } 28 public void joinGame() 29 { 30 System.out.println("有一个小孩加入了"); 31 } 32 }
从上面的例子中可以看到,要是有一个所有对象都能操作的变量就好了,而java中确实有这个变量,叫做静态变量(也叫类变量)
public class Demo1 { public static void main(String []args) { Child ch1 = new Child(3,"小徐"); ch1.joinGame(); Child ch2 = new Child(4,"小白"); ch2.joinGame(); System.out.println("公有="+ch2.total); //也可以直接用类访问静态变量 System.out.println("公有="+Child.total); } } //定义kid类 class Child { int age; String name; //total是静态变量, 因此可以被任何一个对象访问 static int total = 0; public Child(int age,String name) { this.age = age; this.name = name; } public void joinGame() { total++; //在这里进行计数操作 System.out.println("有一个小孩加入了"); } }
什么是:静态变量(类变量)?
类变量是该类的所有对象的共享变量,任何一个该类的对象去访问它是,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
静态变量的定义语法
访问修饰符 static 数据类型 变量名;
静态变量的访问方法
- 类名 . 静态变量名
- 对象名 . 静态变量名
加深静态方法的理解的小例子
1 public class Demo2 2 { 3 static int i=1; 4 static //静态区域块只会被执行一次 5 { 6 i++; 7 } 8 public Demo2() 9 { 10 i++; 11 } 12 13 public static void main(String []args) 14 { 15 Demo2 t1 = new Demo2(); 16 System.out.println(t1.i); 17 Demo2 t2 = new Demo2(); 18 System.out.println(t2.i); 19 20 } 21 }
原理:
1 public class Demo2 2 { 3 static int i=1; 4 static //静态区域块只会被执行一次 5 { 6 i++; 7 System.out.println("静态区域块"); 8 } 9 public Demo2() 10 { 11 i++; 12 System.out.println("成员方法Demo2"); 13 } 14 15 public static void main(String []args) 16 { 17 Demo2 t1 = new Demo2(); 18 System.out.println(t1.i); 19 Demo2 t2 = new Demo2(); 20 System.out.println(t2.i); 21 22 } 23 } 24 25 输出结果: 26 静态区域块 27 成员方法Demo2 28 3 29 成员方法Demo2 30 4
不创建对象static也会执行,原理将来会讲
public class Demo2 { static int i=1; static //静态区域块只会被执行一次 { i++; System.out.println("静态区域块"); } public Demo2() { i++; System.out.println("成员方法Demo2"); } public static void main(String []args) { } } 输出结果: D:\myJavaDemo\Day3>java Demo2 静态区域块
静态方法(类方法)
小例子:
public class Demo3 { public static void main(String []args) { //创建一个学生 Stu stu1=new Stu(29,"aa",340); Stu stu2 = new Stu(29,"aa",290); System.out.println(stu2.getTotalFee()); //此时这个语法是有歧义的,感觉输出的是stu2的学费,但是输出的是所有学生的费用 } } class Stu { int age; String name; int fee; static int totalFee; public Stu(int age,String name,int fee) { this.age = age; this.name = name; totalFee+=fee; } public int getTotalFee() { return totalFee; } }
使用静态方法
java中有一个规则,静态变量原则用静态方法去访问和操作,约定俗成的。并且
- 静态方法中不能对非静态变量操作
- 但普通的成员方法可以操作静态变量,
- 静态变量都可以被操作,非静态方法不能被静态方法操作
1 public class Demo3 2 { 3 public static void main(String []args) 4 { 5 //创建一个学生 6 Stu stu1=new Stu(29,"aa",340); 7 Stu stu2 = new Stu(29,"aa",290); 8 //可以直接使用Stu类名来访问这个静态方法 9 System.out.println(Stu.getTotalFee()); 10 11 } 12 } 13 14 class Stu 15 { 16 int age; 17 String name; 18 int fee; 19 static int totalFee; 20 21 public Stu(int age,String name,int fee) 22 { 23 this.age = age; 24 this.name = name; 25 totalFee+=fee; 26 } 27 public static int getTotalFee() //区别就是这条语句中多了一个static 28 { 29 return totalFee; 30 } 31 }
什么时候使用静态方法?
如果有一个方法(函数)需要让所有的对象去共享的时候,就可以设计成为静态方法
静态方法的语法
访问修饰符 static 数据返回类型 方法名 () { //语句; } //注意静态方法中不能访问非静态变量,例如: 成员属性
使用方法
类名 . 静态方法名 对象名 . 静态方法名
类变量与实例变量的区别
静态变量(类变量) int a; String name; 实例变量 int static a; String static name;
- 加上static称为静态变量或类变量 ,否则称为实例变量
- 类变量是与类相关的,公共的属性
- 实例变量是属于每个对象个体的属性
- 类变量可以通过 类名.类变量名 直接访问
静态方法(类方法)与实例方法的区别
静态方法(类方法) public static int getTotalFee() { return totalFee; } 实例方法 public int getTotalFee() { return totalFee; }
- 类方法属于与类相关的,公共的方法
- 实例方法属于每个对象个体的方法
- 类方法可以通过 类名.类方法名 直接访问
四大特征——抽象、封装、继承、多态
一般是说java有三大特征,即封装、继承、多态。但有人也会把抽象算进去,如顺平
抽象
我们前面在定义一个类的时候,实际上就是把一类事物共有的属性和行为提取出来,形成一个物理模型(模板)。这种研究问题的方法称为抽象。
封装
封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。
就像电视机一样,电路板被保护在内部,我们不能直接操作电路板,但是我们可以通过电视机上的按钮来的操作电路板,从而达到我们的目的。
访问控制修饰符
小例子:访问公有的成员变量
1 public class Demo4 2 { 3 public static void main(String []args) 4 { 5 Clerk clerk1 = new Clerk("小花",24,4567.6f); 6 System.out.println("名字是"+clerk1.name); 7 8 } 9 } 10 11 class Clerk 12 { 13 public String name; //public共有的 14 private int age; //private私有的 15 private float salary; 16 17 public Clerk(String name,int age,float sal) 18 { 19 this.name = name; 20 this.age = age; 21 this.salary = sal; 22 } 23 } 24 25 输出结果: 26 名字是小花
但访问私有的成员变量时,会报错
1 public class Demo4 2 { 3 public static void main(String []args) 4 { 5 Clerk clerk1 = new Clerk("小花",24,4567.6f); 6 System.out.println("名字是"+clerk1.name); 7 8 } 9 } 10 11 class Clerk 12 { 13 public String name; //public共有的 14 private int age; //private私有的 15 private float salary; 16 17 public Clerk(String name,int age,float sal) 18 { 19 this.name = name; 20 this.age = age; 21 this.salary = sal; 22 } 23 } 24 25 报错信息: 26 Demo4.java:11: 错误: salary 在 Clerk 中是 private 访问控制 27 System.out.println("薪水是"+clerk1.salary); 28 ^ 29 1 个错误
通过成员方法去控制和访问私有的属性
1 public class Demo4 2 { 3 public static void main(String []args) 4 { 5 Clerk clerk1 = new Clerk("小花",24,4567.6f); 6 System.out.println("薪水是"+clerk1.getSal()); 7 8 } 9 } 10 11 class Clerk 12 { 13 public String name; //public共有的 14 private int age; //private私有的 15 private float salary; 16 17 public Clerk(String name,int age,float sal) 18 { 19 this.name = name; 20 this.age = age; 21 this.salary = sal; 22 } 23 //通过一个成员方法去控制和访问私有的属性 24 public float getSal() 25 { 26 return this.salary; 27 } 28 } 29 30 输出结果: 31 薪水是4567.6
因为成员方法是公开的(public),可以被使用。
就像我们使用电视机的时候不能通过操作电路板来换台、调节音量,但是我们可以通过操作电视机给我们提供的按钮来进行换台、调节音量的操作。电视机上的按钮就相当于成员方法。
- 厂商不让我们操作电路板,但是让我们操作按钮来间接操作电路板。
- 类不让我们访问私有的属性,但是让我们使用成员方法来访问私有属性。
Java提供四种访问控制修饰符号 控制 方法和变量 的访问权限
- 公开级别:用 pulic 修饰,对外公开
- 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
- 默认级别:没有修饰符号,像同一个包的类公开
- 私有级别:用 private 修饰,只有类本身可以访问,不对外空开
包
从包开始,就不用记事本写程序了,改成用eclipse了
包的必要性?
有这样的一种情况,小白定义了一个类取名为Dog,赛拉也定义了一个类取名为Dog,然后他们俩就打起来了。我们使用myeclipse来模拟一下这种情况
小徐此时站了起来,说:“你们是傻吗?不知道包的作用!”
.代表再分一层
包的作用
- 区分相同名字的类
- 当类很多时,可以很好的管理
- 控制访问范围
打包命令
命令一般放在文件开头的地方
package com.shunping; //这条命令会自动生成,会自动把字节码放到com.shunping这个包中去
命名规范
//包名都是小写字母 , 用 . 隔开 , 比如 com.sina.shunping
常用的包
一个包下,包含很多的类,java中常用的包有:
- java.lang.* —— 这个包是自动引入的
- java.util.* —— 工具包
- java.net.* —— 网络开发包
- java.awt.* —— 窗口工具包
引入一个包
语法 : import 包; import java.awt.* ;
我们引入一个包的主要目的是使用该包下的类
用包来控制访问范围
1 package com.xiaoqiang; 2 3 public class Test 4 { 5 public static void main(String[] args) 6 { 7 Dog dog1 = new Dog(); 8 9 //验证同包下的权限访问情况 10 System.out.println(dog1.a); 11 12 } 13 14 } 15 class Dog 16 { 17 public int a; 18 protected String name; 19 String color; 20 private float price; 21 22 //验证同类下的权限访问情况 23 public void ab1() 24 { 25 System.out.println(this.a); 26 27 } 28 }
同类下的访问权限
同包下的访问权限——没有私有属性的price类
不同包下的访问权限用——用小明去访问小强中的Dog类
在小强的包下新建一个公有的Cat类,里面的内容和Dog相同,此时小明的访问情况为
1 package com.xiaoqiang; 2 3 public class Cat 4 { 5 public int a; 6 protected String name; 7 String color; 8 private float price; 9 10 public void ab1() 11 { 12 System.out.println(this.a); 13 14 } 15 }
权限访问情况为——只能访问公有类
如果我就是想访问其它的属性呢?
——这时就要用到封装的思想,用公有的成员方法去访问私有属性
1 package com.xiaoqiang; 2 3 public class Cat 4 { 5 public int a; 6 protected String name; 7 String color; 8 private float price; 9 10 //提供一个访问name的成员方法 11 public String getName() 12 { 13 return this.name; 14 15 } 16 17 18 }
继承
为什么有继承?
小例子:我们定义小学生,中学生,大学生类
1 public class Demo 2 { 3 public static void main(String[] args) 4 { 5 } 6 7 } 8 9 //小学生类 10 class Pupil 11 { 12 //定义成员属性 13 private int age; 14 private String name; 15 private float fee; 16 17 //交费 18 public void pay(float fee) 19 { 20 this.fee = fee; 21 } 22 } 23 24 //中学生类 25 class MiddleStu 26 { 27 //定义成员属性 28 private int age; 29 private String name; 30 private float fee; 31 32 //交费 33 public void pay(float fee) 34 { 35 this.fee = fee*0.8f; 36 } 37 } 38 39 //大学生类 40 class ColStu 41 { 42 //定义成员属性 43 private int age; 44 private String name; 45 private float fee; 46 47 //交费 48 public void pay(float fee) 49 { 50 this.fee = fee*0.1f; 51 } 52 }
继承就可以很好的解决代码重复问题,让我们的编程更加靠近人类的思维。
当多个类中存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法。这样所有的子类不需要重新定义这些属性和方法,只需要通过extends语句来把父类的这些属性和方法继承过来就行。
1 public class Demo 2 { 3 public static void main(String[] args) 4 { 5 } 6 7 } 8 //将学生的共有属性抽象出来, 做一个父类 9 class Student 10 { 11 public int age; 12 public String name; 13 public float fee; 14 15 } 16 //小学生类 17 class Pupil extends Student{ 18 //交费 19 public void pay(float fee) 20 { 21 this.fee = fee; 22 } 23 } 24 //中学生类 25 class MiddleStu extends Student{ 26 //交费 27 public void pay(float fee) 28 { 29 this.fee = fee*0.8f; 30 } 31 } 32 //大学生类 33 class ColStu extends Student{ 34 //交费 35 public void pay(float fee) 36 { 37 this.fee = fee*0.1f; 38 } 39 }
继承的语法
class 子类 extends 父类 ; //这样子类就会自动拥有父类定义的某些属性和方法,有些东西是继承不了的
深入探讨——父类的哪些属性(变量)、方法被子类继承了
父类: { public int a; protected int b; int c; private int d; public int getA(){} protected int getB(){} int getC(){} private int getD(){} } ————————————继承———————————— 子类: { public int a; protected int b; int c; public int getA(){} protected int getB(){} int getC(){} }
可以看出只有private修饰符的属性和方法不能被子类继承,所以不希望子类继承的属性和方法,只需要把那个属性和方法设置为private属性即可
继承的注意事项
- 子类最多只能继承一个父类(指直接继承),可以通过接口进行多重继承 ,之后会讲
- java所有类都是Object类的子类
- JDK6中有202个包,3777个类、接口、异常、枚举、注释和错误,掌握150个就是大神了
- 在做开发的时候,强烈建议大家多查jdk帮助文档,还是不会就google
import javax.swing.*; public class Demo2 extends JFrame { public static void main(String[] args) { Demo2 demo2 = new Demo2(); } public Demo2() { this.setVisible(true); this.setSize(200 , 200); } }
如果不使用继承的话,需要调用一些复杂的命令
方法重载
在多态前要先了解一下方法重载(overload)和方法覆盖(override)
思考一下:编写一个名为Abc的类,能返回两个整数中较大的一个
- 若果是接收两个float型的数,返回较大数
- 如果是接收散了int型的数,返回最大数
1 public class Demo3 { 2 public static void main(String[] args) { 3 Abc test1 = new Abc(); 4 System.out.println(test1.getMax(23, 78)); 5 } 6 7 } 8 9 class Abc 10 { 11 public int getMax(int i,int j) 12 { 13 if(i>j) 14 { 15 return i; 16 } 17 else 18 { 19 return j; 20 } 21 } 22 }
1 public class Demo3 { 2 public static void main(String[] args) { 3 Abc test1 = new Abc(); 4 Abc test2 = new Abc(); 5 System.out.println(test1.getMax(23, 78)); 6 System.out.println(test1.getMaxFloat(9.8f, 12.2f)); 7 } 8 9 } 10 11 class Abc 12 { 13 public int getMax(int i,int j) 14 { 15 if(i>j) 16 { 17 return i; 18 } 19 else 20 { 21 return j; 22 } 23 } 24 public float getMaxFloat(float a,float b) 25 { 26 if(a>b) 27 { 28 return a; 29 } 30 else 31 { 32 return b; 33 } 34 } 35 }
可以看出我们是又专门加一个,比较小数的成员方法,有没有方法用一个方法来进行比较呢?
这个时候有可以利用方法重载的特性——可以定义重名的两个成员方法,让编译器自己选择用哪个?
1 package com.xiaohui; 2 /* 3 * 作者:我聊啊 4 * 时间:2018.9.11 5 * 功能:了解方法重载 6 */ 7 public class Demo3 { 8 public static void main(String[] args) { 9 Abc test1 = new Abc(); 10 Abc test2 = new Abc(); 11 System.out.println(test1.getMax(23, 78)); 12 System.out.println(test1.getMax(9.8f, 12.2f)); 13 } 14 15 } 16 17 class Abc 18 { 19 public int getMax(int i,int j) 20 { 21 if(i>j) 22 { 23 return i; 24 } 25 else 26 { 27 return j; 28 } 29 } 30 public float getMax(float a,float b) 31 { 32 if(a>b) 33 { 34 return a; 35 } 36 else 37 { 38 return b; 39 } 40 } 41 }
方法重载的概念
简单地说:方法重载就是在类的同一种功能的多种实现方式,到底使用哪种方式,取决于调用者给出的参数。
注意事项
- 方法名一定相同
- 方法的参数类型,个数,顺序至少有一项不同——(顺序:(int a , double b)改成(double a , int b))
- 返回类型也可以不相同,但是如果只有返回类型不一样,是不能够构重载的
- 方法的访问控制修饰符可以不同,如果只是修饰符不同,也是不能够构成重载的
方法的覆盖(重写)
既然子类可以继承父类的属性和方法,这样可以提高代码的复用性,这个很好,可是问题来了!!
假设我要写三个类——猫、狗、猪,显然这三个都是动物,他们之间一定存在着相同的特点。根据类的抽象特征,我们可以把他们的相同点提取出来,形成一个父类Animal,然后继承。
但是问题来了,动物都会叫,但是叫声是不一样的,怎样解决子类和父类方法的异同!
这是就体现出了方法覆盖(重写)的特性了
1 public class Demo4 2 { 3 public static void main(String[] args) { 4 Cat cat1 = new Cat(); 5 cat1.cry(); 6 7 Dog dog1 = new Dog(); 8 dog1.cry(); 9 } 10 11 } 12 13 class Animal 14 { 15 int age; 16 String name; 17 //动物都会叫 18 public void cry() 19 { 20 System.out.println("我是动物,不知道怎么叫"); 21 } 22 } 23 class Cat extends Animal 24 { 25 //覆盖了父类的方法 26 public void cry() 27 { 28 System.out.println("喵喵喵"); 29 } 30 } 31 32 class Dog extends Animal 33 { 34 //覆盖了父类的方法 35 public void cry() 36 { 37 System.out.println("汪汪汪"); 38 } 39 }
方法重写的核心思想:子类的某些方法和父类不一样,需要覆盖掉父类的方法
方法覆盖的概念
简单的说:方法覆盖就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法。
注意事项
- 子类的方法的返回类型,参数,方法名称要和父类方法的返回类型完全一致,否则编译会出错
- 子类方法不能缩小父类方法的访问权限,换句话说子类的权限可以比父类高
多态
所谓多态,就是指一个引用(类型)在不同情况下的多种状态。也可以这样理解:多态是指通过指向父类的指针,来调用在不同子类中实现的方法
案例
1 public class Demo6 2 { 3 public static void main(String[] args) 4 { 5 //多态 6 Animal an;//创建了一个Animal类引用变量,Animal类引用就是以后可以用来指向Animal对象的对象引用 7 an =new Cat(); //让这个动物的引用指向了猫这个实例(对象) 8 an.cry(); 9 an = new Dog(); 10 //以Dog类为模板,在堆空间里创建一个Dog类对象,简称为Dog对象 11 an.cry(); 12 //an这个引用会自动判断引用是那种类型的 13 } 14 } 15 //动物类 16 class Animal 17 { 18 String name; 19 int age; 20 public String getName() { 21 return name; 22 } 23 public void setName(String name) { 24 this.name = name; 25 } 26 public int getAge() { 27 return age; 28 } 29 public void setAge(int age) { 30 this.age = age; 31 } 32 33 //动物会叫 34 public void cry() 35 { 36 System.out.println("不知道怎么叫"); 37 } 38 39 } 40 class Cat extends Animal 41 { 42 //猫自己叫 43 public void cry() 44 { 45 System.out.println("喵喵喵"); 46 } 47 } 48 class Dog extends Animal 49 { 50 //狗自己叫 51 public void cry() 52 { 53 System.out.println("汪汪汪"); 54 } 55 } 56 57 输出结果: 58 喵喵喵 59 汪汪汪
如果没有这个特性,狗要叫就要创建一个狗的引用,猫要叫就要创建一个猫的引用,动物再多一点就会不方便管理。当然多态也能调用孙子类的方法。
1 package com.xiaohui; 2 3 public class Demo7 4 { 5 public static void main(String[] args) 6 { 7 Master master = new Master(); 8 master.feed(new Dog(), new Bone()); 9 master.feed(new Cat(),new Fish()); 10 //我想要他喂那种动物就喂那种懂我,我想喂他吃什么就吃什么 11 // 12 } 13 14 } 15 //主人类 16 class Master 17 { 18 //给动物喂食物,使用多态,方法就可以用一个 19 public void feed(Animal an,Food f) 20 { 21 an.eat(); 22 f.showName(); 23 } 24 } 25 26 class Food 27 { 28 String name; 29 public void showName() 30 { 31 32 } 33 } 34 class Fish extends Food 35 { 36 public void showName() 37 { 38 System.out.println("鱼"); 39 } 40 } 41 class Bone extends Food 42 { 43 public void showName() 44 { 45 System.out.println("骨头"); 46 } 47 } 48 //动物类 49 class Animal 50 { 51 String name; 52 int age; 53 //动物会吃 54 public void eat() 55 { 56 System.out.println("不知道吃什么"); 57 } 58 } 59 60 class Cat extends Animal 61 { 62 //猫进食 63 public void eat() 64 { 65 System.out.println("猫爱吃鱼"); 66 } 67 } 68 69 class Dog extends Animal 70 { 71 //狗进食 72 public void eat() 73 { 74 System.out.println("狗爱吃骨头"); 75 } 76 }
如果Food类和Animal类下的子类有许多的话,Master类中的方法是无需改变的,只需要输入对应的动物和事物就可以了。否则我们想要狗吃骨头和猫吃鱼就要用这么多的代码来写
Dog dog1 = new Dog(); dog1.eat(); Bone bone1 = new Bone(); bone1.showName(); Cat cat1 = new Cat(); cat1.eat(); Fish fish1 = new Fish(); fish1.showName();
引用的注意事项:
- Java允许父类的引用变量引用它的子类的对象(对象)
Animal animal = new Cat()
这种转换是自动完成的
- 类型转换还有一些具体的细节要求,之后会进一步学医,比如子类能不能转换成父类,有什么要求等等...