我们程序设计要求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
封装即:属性私有,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()); } }语法:“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子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权力对这个方法进行重新编写,有必要进行方法的覆盖
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…
什么是多态?
多种形态,多种状态,编译和运行有两个不同的状态
编译期叫做静态绑定
运行期叫做动态绑定
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
多态存在的条件:
有继承关系子类重写父类的方法父类引用指向子类对象基础语法:
向上转型:子------>父(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(类型转换异常) */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"); } }