JavaSE笔记06面向对象编程02

it2024-12-14  14

面向对象编程02

1.封装

我们程序设计要求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用

封装即:属性私有,get/set

package com.oop.demo04; //类 public class Student { //private:私有 //名字 private String name; //学号 private int id; //性别 private char sex; //年龄 private int age; //提供一些可以操作这个属性的方法 //提供一些public的get、set方法 //get 获得这个数据 public String getName(){ return this.name; } //set 给这个数据设置值 public void setName(String name){ this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int a) {//不合法 if (a> 120 || a < 0){ System.out.println("输入年龄不合法!"); }else { this.age = a; } } /*快捷键: 1.Alt + insert弹出小窗口 2.选择Getter and Setter 3.选择要私有化的属性,点OK即可 */ //注意:set和get方法不加static } package com.oop.demo04; /* 作用: 1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 4.系统可维护性增加了 */ public class Application { public static void main(String[] args) { Student s1 = new Student(); Student s2 = new Student(); //s1.name = "XX";属性私有化后不能这么写,会报错 s1.setName("阿波"); System.out.println(s1.getName());//阿波 //不合法的,需要在set方法中设立关卡来保证数据的安全性 s1.setAge(999); System.out.println(s1.getAge()); s2.setAge(120); System.out.println(s2.getAge()); } }

2.继承

继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。继承关系的两个类,一个为子类,一个为父类。子类继承父类,使用关键字extends来表示。extends的意思是“扩展”。子类是父类的扩展。子类和父类之间,从意义上讲应该具有“is a”的关系。Java中类只有单继承,没有多继承!一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子。 package com.oop.demo05; //在java中所有的类,都默认直接或者间接继承Object类 /* Java中的类没有显示继承任何类。则默认继承object类,object类是java语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有object类型中的所有特征 */ //人: 父类 public class Person /*extends Object*/ { private int money = 10_0000_0000; public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public void say(){ System.out.println("说了一句话"); } } package com.oop.demo05; //学生 is 人 : 子类 //Ctrl + H 可以显示继承的结构图 public class Student extends Person{} package com.oop.demo05; //老师 is 人 :子类 public class Teacher extends Person{} package com.oop.demo05; public class Application { public static void main(String[] args) { Student s1 = new Student(); s1.say();//说了一句话 System.out.println(s1.getMoney());//1000000000 } }

Super

语法:“super.”,“super()”

注意点:

super调用父类的构造方法,必须在构造方法的第一行super必须只能出现在子类的方法或者构造方法中super和this不能同时调用构造方法!当构造方法没有this()也没有super(),默认会有一个super()

super与this

代表的对象不同:

this:本身调用者这个对象

super:代表父类对象的引用

前提:

this:没有继承也可以使用

super:只能在继承条件下才可以使用

构造方法:

this():本类的构造!

super():父类的构造!

Public class Test{ Public static void main(String[] args){ //创建子类对象 new C(); } } Class A{ Public A(){ System.out.println(1); } } Class B extends A{ Public B(){ System.out.println(2); } Public B(String name){ //super(name);没写会默认自动创建super() System.out.println(3); } } Class C extends B{ Public C(){ this(“张三”); system.out.println(4); } Public C(String name){ this(name,20); System.out.println(5); } Public C(String name,int age){ Super(name); System.out.println(6); } }//运行结果:1 3 6 5 4

方法重写(方法覆盖)override

子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权力对这个方法进行重新编写,有必要进行方法的覆盖

Pubic class Test{ Public static void main(String[] args){ //创建对象 ChinaPeople p1 = new ChinaPeople(); P1.setName(“张三”); P1.speak();//张三正在说汉语 AmericPeople p2 = new AmericPeople(); P2.setName(“Jack”); P2.speak();//jack speak English } } Class People{//父类,人类 Private String name; //构造方法 Public People(){} Public People(String name){ this.name = name; } Public void setName(String name){ this.name = name; } Public String getName(){ return name; } //方法 Public void speak(){ System.out.println(name + “……”); } } Class ChinaPeople extends People{//子类 Public void speak(){ System.out.println(this.getName() + “正在说汉语”); } } Class AmericPeople extends People{//子类 Public void speak(){ System.out.println(this.getName() + “speak English”); } }

注意:

方法覆盖只针对方法,和属性无关

私有方法无法覆盖,静态方法不谈覆盖

构造方法不能被继承,所以也不能被覆盖

快捷键:Alt + Insert 选择 Override Methods…

3.多态

什么是多态?

多种形态,多种状态,编译和运行有两个不同的状态

编译期叫做静态绑定

运行期叫做动态绑定

即同一方法可以根据发送对象的不同而采用多种不同的行为方式。一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多

多态存在的条件:

有继承关系子类重写父类的方法父类引用指向子类对象

基础语法:

向上转型:子------>父(upcasting) Animal a = new Cat();

向下转型:父------>子(downcasting) Cat c = (Cat)a;

注意:java中允许向上与向下转型,无论是哪种,必须有继承关系,没有继承关系编译器会报错。

package com.oop.demo06; public class Person { public void run(){ System.out.println("run"); } } package com.oop.demo06; public class Student extends Person { public void run(){ System.out.println("son"); } public void eat(){ System.out.println("eat"); } } package com.oop.demo06; public class Application { public static void main(String[] args) { /* 一个对象的实际类型是确定的 new Student(); new Person(); */ //可以指向的引用类型就不确定了:父类的引用指向子类 //Student 能调用的方法都是自己的或者继承父类的 Student s1 = new Student(); //Person父类型,可以指向子类,但是不能调用子类独有的方法 Person s2 = new Student(); Object s3 = new Student(); //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大 s1.run();//son s2.run();//son s1.eat();//eat //s2.eat();报错 //子类重写了父类的方法,执行子类的方法,由于父类中没有eat方法,这是子类独有的方法,所以报错 //强制转型便不会报错 ((Student) s2).eat();//eat } }

再举个例子

Public calss Test01{ Public static void main(String[] args){ Animal a1 = new Animal(); a1.move(); //动物在移动! Cat c1 = new Cat(); c1.move(); //猫在走猫步! Bird b1 = new Bird(); b1.move(); //鸟儿在飞翔! Animal a2 = new Cat(); Animal a3 = new Bird(); /* 分析:Animal是父类,Cat和Bird是子类,Cat和Bird is a Animal,这句话能不能说通?能。a2和a3就是父类的引用,new Cat()和new Bird()是一个子类型的对象,经过测试得知:父类型的引用允许指向子类型的对象。 */ a2.move(); //猫在走猫步!(向上转型) a3.move(); /* 分析:编译阶段:编译器只知道a2的类型是Animal,所以编译器在检查语法的时候会去Animal.Class字节码文件中找move()方法,找到绑定上move()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定) 运行阶段:实际上在堆内存中创建的java对象是cat对象,所以move的时候,真正参与move的对象是一只猫,于是运行的阶段会动态执行cat对象的move()方法,这个过程属于运行阶段绑定。(运行阶段属于动态绑定) */ Animal a2 = new Cat(); //底层对象是cat A5.catchMouse(); //错误,找不到符号 /* Why?因为编译器只知道a5的类型是Animal,去Animal.class文件中找catchMouse()方法,没找到,所以静态绑定失败,编译报错,无法运行。 */ //这个时候必须使用向下转型 Cat x = (Cat) a5; x.catchMouse(); //猫正在抓老鼠! //因为Animal和Cat存在继承关系,所以Animal转成Cat没报错 } } Class Animal{ //父类,动物类 Public void move(){ System.out.println(“动物在移动!”); } } Class Cat extends Animal{ //猫类,子类 Public void move(){ System.out.println(“猫在走猫步!”); } Public void catchMouse(){ //猫自己特有的行为 System.out.println(“猫正在抓老鼠!”); } } Class Bird extends Aniaml{ Public void move(){ System.out.println(“鸟儿在飞翔!”); } } /* 向下转型的风险:Animal a6 = new Bird();表面上是Aniaml,运行的时候是Bird。 Cat y = (Cat) a6; y.catchMouse(); 分析:编译器检测到a6是Animal类型,而Animal和Cat之间存在继承关系,所以编译没毛病,运行阶段,堆内存实际创建的对象是Bird,Bird对象转换成Cat对象就不行了,因为Bird和Cat之间没有继承关系。 运行出现异常:java,lang.ClassCastException(类型转换异常) */

4.instanceof和类型转换

instanceof可以在运行阶段动态判断引用指向的对象的类型

语法:(引用 instanceof 类型)

instanceof运算符的运算结果只能是true或false

package com.oop.demo06; public class Application { public static void main(String[] args) { //Object > Person > Student Object object = new Student(); System.out.println(object instanceof Student);//true System.out.println(object instanceof Person);//true System.out.println(object instanceof Object);//true System.out.println(object instanceof Teachet);//false System.out.println(object instanceof String);//false System.out.println("================================"); Person person = new Student(); System.out.println(person instanceof Student);//true System.out.println(person instanceof Person);//true System.out.println(person instanceof Object);//true System.out.println(person instanceof Teachet);//false //System.out.println(person instanceof String);//编译报错 System.out.println("================================"); Student student = new Student(); System.out.println(student instanceof Student);//true System.out.println(student instanceof Person);//true System.out.println(student instanceof Object);//true //System.out.println(student instanceof Teachet);//编译报错 //System.out.println(student instanceof String);//编译报错 System.out.println("================================"); //类型之间的转换 Person p = new Student(); //p.go();报错 //将这个对象转换为Student类型,我们就可以使用Student类型的方法了! Student s = (Student)p; s.go();//go //简化后如下 ((Student) p).go();//go /* 子类转换为父类,可能丢失自己本来的一些方法 */ } } package com.oop.demo06; public class Person { public void run(){ System.out.println("run"); } } package com.oop.demo06; public class Student extends Person { public void go(){ System.out.println("go"); } }
最新回复(0)