面向对象高阶
面向对象进阶
1.封装
封装的意义在于保护或者防止代码(数据)被无意中破坏。保护成员属性,不让类以外的程序直接访问和修改。
封装原则:隐藏对象的属性和实现细节,仅对外公开访问方法,并且控制访问级别。
/**
* 封装
* @author 孟祥宽
*
*/
public class Demo1 {
public static void main(String[] args) {
Person1 person = new Person1();
person.setName("孟祥宽");
person.setAge(20);
person.say();
}
}
class Person1{
private String name;
private int age;
// 构造方法
public Person1() {
this.("默认名字",1);
System.out.println("默认名字:" + this.name + "\n默认年龄:" + age);
}
public Person1(String name, int age) {
this.name = this.setName(name);
this.setAge(age);
}
// set和get方法
public String setName(String name) {
return this.name = name;
}
public String getName() {
System.out.println("名字:" + this.name);
return this.name;
}
public int getAge() {
System.out.println("年龄:" + this.age);
return age;
}
public void setAge(int age) {
if(age > 150 || age < 0) {
this.age = 1;
} else {
this.age = age;
}
}
public void say() {
System.out.println("姓名:" + name + "\n年龄:" + age);
}
}
运行结果:
1.1 this关键字
在Java基础中,this关键字是一个重要的概念。使用this关键字可以完成以下操作:
- 调用类中的属性
- 调用类中的方法或者构造方法
- 在一个构造函数中,调用另一个构造方法时,调用的代码,必须编写在构造方法的第一行
- 表示当前对象
public String setName(String name) {
/**
* 这个this表示对象
*/
return this.name = name;
}
public Person1() {
/**
* 表示调用类的构造方法
*/
this.("默认名字",1);
System.out.println("默认名字:" + this.name + "\n默认年龄:" + age);
}
1.2 static关键字
static表示“静态”的意思,可以用来修饰成员变量和成员方法。static的主要作用在于创建独立于具体对象的域变量或者方法,即不用依赖于对象,使用类就可以调用。
简单理解:
被static关键字修饰的方法或者变量不需要依赖对象来进行访问,只要类被加载,就可以通过类名去进行访问。并且不会因为对象的多次创建而在内存中创建多份数据。

重点:
- 静态成员在类加载的时候加载并初始化。
- 无论一个类存在多少个对象,静态的属性,永远在内存中只有一份(可以理解为所有对象共用)。
- 在访问时,静态不能访问非静态,非静态可以访问静态。
public class Demo3 {
public static void main(String[] args) {
Person3.show();
System.out.println();
Person3 p = new Person3("孟祥宽");
p.showPerson();
Person3 p2 = new Person3("mxk");
p2.showPerson();
}
}
class Person3 {
private static int index;
private String name;
public Person3() {}
public Person3(String name) {
index ++;
this.setName(name);
}
public static int getIndex() {
return index;
}
public static void setIndex(int index) {
Person3.index = index;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 静态方法
public static void show() {
System.out.print(index + ".用户:");
// this.getName(); -> static在类加载的时候加载,可能没有创建对象,所以不能用this.
// getName(); -> 同理,普通方法依赖于对象,静态方法里不能调用非静态方法.
}
@SuppressWarnings("static-access")
public void showPerson() {
this.show();
System.out.println(this.name);
}
}
运行结果:
2.继承
继承就是子类继承父类的特征(属性)和行为(方法),使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承的限制:Java中只有单继承,多重继承没有多继承。C++有多继承。一个孩子只能有一个爹。
public class Student extends Person {// Student 继承 Person(父类)
}

2.1 super关键字
/**
* 通过super:可以访问父类的构造方法
* 调用super的构造方法要把super()放在第一行
* 不存在同时调用this和super方法
* 可以访问父类的属性
* 可以访问父类的方法
* @param name
* @param age
* @param subject
*/
public Student(String name, int age, String subject) {
super(name,age);// 父类的构造函数
index++;
this.setSubject(subject);
}
2.2 重写 override
重写的规则:
- 参数列表必须完全与被重写方法的相同;
- 返回类型必须完全与被重写方法的返回类型相同;
- 访问权限不能比父类中被重写的方法的访问权限更低。比如:父类用public 子类不能用protected;
- 父类的成员方法只能被它的子类重写;
- 声明为static、private的方法不能被重写,但是能够被再次声明;
面试题:重写与重载的区别?
答案:
- 发生的位置。
- 重载:一个类中
- 重写:子父类中
- 参数列表限制。
- 重载:必须不同
- 重写:必须相同
- 返回值类型。
- 重载:与返回值类型无关
- 重写:必须一致
- 访问权限。
- 重载:与访问权限无关
- 重写:子的方法权限必须不能小于父的方法权限
- 异常处理。
- 重载:与异常无关
- 重写:可以更精准范围更小但是不能抛出新的异常
2.3 final关键字
-
用于修饰属性、变量;
-
变量成为了常量,无法对其在此进行赋值。
-
final修饰的局部变量,只能赋值一次(可以先声明后赋值)。
-
final修饰的成员属性,必须在声明时赋值。
-
※全局常量:public static final
常量的命名规范:由一个或多个单词组成,单词语单词之间必须使用下滑线隔开,单词中所有字母大写。
示例:BASE_INFO
-
-
-
用于修饰类;
- 不可以被继承
-
用于修饰方法;
- 不可以被子类重写
public static void main(String[] args) {
final int a = 5;// 变量成为了常量,无法对其再次进行赋值
/* 报错:The final local variable a cannot be assigned. It must be blank and not using a compound assignment
翻译:无法指定最终的局部变量a。它必须为空且不使用复合赋值
*/
// a = 21;
System.out.println(a);
final int a1;
a1 = 20;
System.out.println(a1);
}
3.多态
对象的多种表现形式。子类就是父类的一种形态。
重写(override)和重载(overload)也是多态的体现。
- 重写:子父类的方法多态性
- 重载:一个类的方法多态性
/**
* 抽象类
* @author 孟祥宽
*
*/
public abstract class Person {
// 姓名
private String name;
// 年龄
private int age;
// 构造方法
public Person() {
this("默认姓名", 18);
}
public Person(String name, int age) {
this.setAge(age);
this.setName(name);
}
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 150 || age < 0) {
System.err.println("年龄错误!默认为18岁");
this.age = 18;
}else {
this.age = age;
}
}
// show 方法
public abstract void show();
}
/**
* Student 类
* @author 孟祥宽
*
*/
public class Student extends Person {
// 学校
private String school;
// 构造方法
public Student() {
super();
this.school = "默认学校";
}
public Student(String name, int age, String school) {
super(name, age);// 父类的构造方法
this.setSchool(school);
}
// getter setter
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
/**
* 重写show方法
*/
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("姓名:" + super.getName() + ";\n年龄:" + super.getAge() + ";\n学校:" + this.school + ".");
}
/**
* 重载
*/
public String show(String name, int age, String school) {
this.setAge(age);
this.setName(name);
this.setSchool(school);
System.out.println("姓名:" + super.getName() + ";\n年龄:" + super.getAge() + ";\n学校:" + this.school + ".");
return "姓名:" + super.getName() + ";\n年龄:" + super.getAge() + ";\n学校:" + this.school + ".";
}
}
import com.kaikeba.test.pojo.*;
/**
* 测试类
* @author 孟祥宽
*
*/
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.show();
System.out.println("------------------");
student.show("多态",15,"java");
System.out.println("------------------");
Student student2 = new Student("孟祥宽",25,"长春理工大学");
student2.show();
System.out.println("------------------");
Nurse nurse = new Nurse("小梦",18,"沈阳工学院");
nurse.show();
System.out.println("------------------");
Driver driver = new Driver("大梦",40,"新东方");
driver.show();
System.out.println("------------------");
// 父类引用子类
Person person = new Student("小吴",24,"大连理工");
person.show();
System.out.println("------------------");
Person person2 = new Nurse("小李",30,"白城市医院");
person2.show();
}
}
运行结果:
3.1 对象类型转换
/**
*
* 父类
*/
public class Person {}
/**
*
* 子类
*/
public class Student extends Person {} // 继承
/**
*
* 子类
*/
public class Nurse extends Person {} // 继承
/**
*
* 测试类
*/
public class Test {
public static void main(String[] args) {
// 向上转换 即 子类转换成父类
Person person = new Student();
// 向下转换 即 父类转换成子类 需要强转
Student student = (Student) person;
Person person2 = new Nurse();
// ClassCastException异常
Student student2 = (Student) person2;// 此时会报错 因为 person2 引用的是Nurse类 不能请转成Student类
}
}
3.2 instanceof关键字
判断某个对象是否是指定类的实例。
public static void main(String[] args) {
// 父类引用子类
Person person = new Student("小吴",24,"大连理工");
person.show();
say(person);
System.out.println("------------------");
Person person2 = new Nurse("小李",30,"白城市医院");
person2.show();
}
public static void say(Person person) {
// 判断传入的对象是此对象那种形态
String str = person instanceof Student ? "Student":"";
System.out.println("这是一个" + str);
}
运行结果:

浙公网安备 33010602011771号