Java 面向对象编程(第二篇)
1. 封装
通常,应禁止直接访问一个对象中的数组的实际表示,而应通过操作接口来访问,这称为信息的隐藏
属于私有,get/set
封装:
package com.oop.demo04;
// 类 private:私有
public class Student {
//属性私有
//名称
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;
}
// Alt+insert
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 age) {
if(age>120 || age<0){
this.age = 3;
}else{
this.age = age;
}
}
}
- 提高代码的安全性,保护数据
- 提高代码的实现细节
- 统一接口
- 系统的可维护性增加了
调用:
package com.oop.demo04;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
String name = s1.getName();
System.out.println(name);
s1.setName("zzk");
System.out.println(s1.getName());
s1.setAge(40); // 不合法
System.out.println(s1.getAge());
}
}
2. 继承
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extends的意思是“扩展”。子类是父类的扩展!
JAVA中类只有单继承,没有多继承!
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用extends来表示
子类和父类之间,从意义上讲应该具有“is a”的关系。
object类
super
方法重写
2.1 object类
package com.oop.demo05;
// 在Java中,所有的类,都直接或者间接继承Object类
// 人
public class Person /*extends Object*/{
// public 公共的
// protected 保护
// default 默认
// private 私有的
private int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
2.2 super
super注意点
1.super是调用父类的构造方法,必须在构造方法的第一个。
2.super必须只能吃现在子类的方法或者构造方法中!
3.super 和 this 不能同时调用构造方法!
super vs this
代表的对象不同:
1.this:本身调用者这个对象
2.super:代表父类对象的应用
前提:
this:在没有继承的情况下也可以使用。
super:只能在继承条件下才可以使用。
构造方法
this();本类的构造
super();父类的构造
package com.oop.demo05;
// 学生
public class Student extends Person{
private String name = "mango";
public Student() {
// 隐藏代码:调用了父类的无参构造
// 调用父类的构造器 必须要在子类构造器的第一行
// 父类如果没有无参构造,子类就无法使用无参构造
super();
//this() 只能调用一个
System.out.println("Student无参执行了");
}
public Student(String name) {
this.name = name;
}
public void print(){
System.out.println("Student");
}
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public void test1(){
print();
this.print();
super.print();
}
}
2.3 方法的重写
重写都方法的重写,和属性无关
2.3.1 静态方法(static)
A:
package com.oop.demo05;
public class A extends B{
public static void test() {
System.out.println("A=>test()");
}
}
B:
package com.oop.demo05;
// 重写都方法的重写,和属性无关
public class B {
public static void test() {
System.out.println("B=>test");
}
}
输出结果:
A=>test() B=>test
2.3.2 非静态方法
A:
package com.oop.demo05;
public class A extends B{
@Override
public void test() {
System.out.println("A=>test()");
}
}
B:
package com.oop.demo05;
// 重写都方法的重写,和属性无关
public class B {
public void test() {
System.out.println("B=>test");
}
}
输出结果:
A=>test() A=>test
区别:
静态方法调用只和左边,定义的数据类型有关
非静态方法重写了父类的方法
非静态的才是重写!!!(重写的关键字是public)
重写总结:
- 需要有继承关系,子类重写父类的方法!
- 方法名必须相同。
- 参数列表必须相同。
- 修饰符:可以被扩大,但是不可以缩小。public>protected>default>private
- 抛出异常:范围,可以被缩小,但不能扩大:ClassNotFoundException --> Exception
- 重写,子类的方法和父类必要一致:方法体不同!
为什么需要重写?
- 父类的功能,子类不一定需要,或者不一定满足!
- Alt + Insert : override; 重写
3.多态
- 动态编译:动态编辑
- 即同一种方法可以根据发送对象的不同而采用多种不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。
多态存在的条件:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意:多台是方法的多态,属性没有多态性。instanceof
主程序:
package com.oop.demo06;
public class Application {
public static void main(String[] args) {
// 一个对象的实际类型是确定的
// 可以指向的引用类型就不确定:父类的引用指向子类
// Student 能调用的方法都是自己的 或者都是继承父类的
Student s1 = new Student();
// Person 父类型,可以指向子类,但是不能调用子类独有的方法。
Person s2 = new Student();
Object student = new Student();
s2.run(); // 子类重写了父类的方法
s1.run();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
((Student) s2).eat(); // 子类重写了父类的方法,执行子类的方法
s1.eat();
}
}
子类:
package com.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
父类:
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
注意事项:
- 多态是方法的多态,属性没有多态。
- 父类和子类,有联系 类型转换异常! ClassCastException!
- 存在的条件:继承关系、方法需要重写,父类的引用指向子类对象!Father f1 = new Son();
无法重写(无法多态):
1.static 方法,属于类,它不属于实例
2.final 常量
3.private 方法
4. instanceof 关键字
System.out.println(X instanceof Y);//能不能编译通过! X和Y有没有父子关系!
package com.oop.demo06;
public class Application {
public static void main(String[] args) {
// Object -> Person -> Student
Object o = new Student();
// System.out.println(X instanceof Y);//能不能编译通过! X和Y有没有父子关系!
System.out.println(o instanceof Student);
System.out.println(o instanceof Person);
System.out.println(o instanceof Object);
System.out.println(o instanceof Teacher);
System.out.println(o instanceof String);
System.out.println("===============");
/*
*
* true
true
true
false
false
*/
// Person -> Student
Person p = new Student();
System.out.println(p instanceof Student); // true
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Object); // true
System.out.println(p instanceof Teacher); // false
//System.out.println(p instanceof String); // 编译就报错
System.out.println("===============");
Student s = new Student();
System.out.println(s instanceof Student); // true
System.out.println(s instanceof Person); // true
System.out.println(s instanceof Object); // true
//System.out.println(s instanceof Teacher); // 编译就报错
//System.out.println(p instanceof String); // 编译就报错
}
}
5. 类型转换
父转子:
package com.oop.demo06;
public class Application {
public static void main(String[] args) {
// 类型之间的转换:基本类型转换 高低
// 类型之间转换: 父类 子类
// 高 低
Person student = new Student();
// student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
((Student)student).go();
}
}
子转父:
子类转换为父类,可能会丢失自己本来的一些方法!
package com.oop.demo06;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.go();
Person person = student;
}
}
小结:
- 父类引用指向子类的对象。
- 把子类转换为父类,向上转型;可能用不了子类的方法
- 把父类转换为子类,向下转型;(强制转换)
- 方便方法的调用,减少重复的代码。