本文主要是介绍七、面向对象编程(中级),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、IDEA
- 1.1 IDEA下载安装
- 1.2 IDEA的使用
- 1.3 IDEA常用的快捷键
- 二、包
- 2.1 包的基本介绍
- 2.2 包的本质分析
- 2.3 包的命名
- 2.4 常用的包
- 2.5 如何引入包
- 三、访问修饰符
- 四、面向对象的三大特征
- 4.1 封装
- 4.2 继承
- 4.2.1 为什么需要继承
- 4.2.2 继承的基本介绍
- 4.2.3 继承的深入讨论/细节问题
- 4.2.4 继承的本质分析(内存分析,重要)
- 4.3 super关键字
- 4.4 super与this的比较
- 4.5 方法重写/覆盖(override)
- 4.6 方法重写与重载比较
- 4.7 多态
- 4.7.1 基本介绍
- 4.7.2 多态注意事项和细节讨论
- 4.7.3 java的动态绑定机制(非常非常重要)
- 4.7.4 多态的应用
- 五、Object类详解
- 5.1 equals方法
- 5.2 hashCode方法
- 5.3 toString()方法
- 5.4 finalize方法
- 六、断点调试
- 七、细节知识
- 7.1 访问修饰符
- 7.2 继承的细节
- 7.3 继承的本质分析(内存分析,重要)
- 7.4 super细节
- 7.5 方法重写的细节
- 7.6 多态的理解
- 7.7 java的动态绑定机制(非常非常重要)
一、IDEA
1.1 IDEA下载安装
1.2 IDEA的使用
1.3 IDEA常用的快捷键
二、包
2.1 包的基本介绍
2.2 包的本质分析
2.3 包的命名
2.4 常用的包
2.5 如何引入包
建议:我们需要使用哪个类就导入哪个类,不建议使用 *
导入
三、访问修饰符
注:上述多个访问范围之间是或的关系(如:protected修饰的属性或方法可以被 同类
或 同包
或 子类
访问);另外 同包
指的是 完全相同的包路径
(子包路径不算相同)
四、面向对象的三大特征
- 基本介绍
面向对象编程有三大特征:封装
、继承
和多态
4.1 封装
-
基本介绍
-
封装的理解和好处
-
封装的实现步骤
-
快速入门
public class Hello {public static void main(String[] args) {Person person = new Person();person.setAge(900);}
}class Person {public String name;private int age;private double salary;private String job;public Person() {}public Person(String name, int age, double salary, String job) {setAge(age);setJob(job);setName(name);setSalary(salary);}public void setName(String name) {if (name.length() >= 2 && name.length() <= 6) {this.name = name;return;}System.out.println("输入的名字长度必须在2-6之间");}public void setAge(int age) {if (age >= 1 && age <= 120) {this.age = age;return;}System.out.println("年龄必须在1-120");}public void setSalary(double salary) {this.salary = salary;}public void setJob(String job) {this.job = job;}public String getName() {return name;}public int getAge() {return age;}public double getSalary() {return salary;}public String getJob() {return job;}
}
4.2 继承
4.2.1 为什么需要继承
4.2.2 继承的基本介绍
4.2.3 继承的深入讨论/细节问题
// 基础父类
package com.extends_;public class Base {// 4个属性public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public int getN4() { // 构建公共方法使子类可以访问私有属性return this.n4;}public Base() {}public void test100() {System.out.println("test100()....");}protected void test200() {System.out.println("test200()....");}void test300() {System.out.println("test300()....");}private void test400() {System.out.println("test400()....");}
}
// 子类(与父类同包)
package com.extends_;public class Sub extends Base {public Sub() {}public void sayOk() {// 非私有的属性和方法可以在子类直接访问// 私有属性和方法不能在子类直接访问(n4无法直接访问)System.out.println(n1 + "" + n2 + "" + n3);int n4 = getN4();// 通过父类的公共方法对私有属性进行访问System.out.println("n4:"+n4);test100();test200();test300();
// test400(); 无法直接访问}
}
- 注意第6点,使用了
this()
后则编译器不会默认添加一个super()
4.2.4 继承的本质分析(内存分析,重要)
public class ExtendsTest{public static void main(String[] args){Son son = new son(); // 内存的布局System.out.println(son.age); // 访问父类中的属性age}
}class GrandPa{String name = "大头爷爷";String hobby = "旅游";
}class Father extends GrandPa{String name = "大头爸爸";int age = 39;
}class Son extends Father{String name = "大头儿子";
}
- 执行流程:
- 在
方法区
中加载类信息
,顺序由继承关系决定(Object
-->GrandPa
-->Father
-->Son
)并建立类之间的关系 - 在堆中创建Son的实例,按
继承关系
创建属性
并初始化
(各父类中的变量会存储在独立的二级堆空间
中) - 将Son实例的引用赋值给
main方法栈
中的son引用变量
- 若使用son调用
属性
或方法
,则遵守以下原则:- 首先看子类是否有该
属性
(方法
) - 如果子类有这个
属性
(方法
),并可以访问,则返回信息 - 如果子类没有这个
属性
(方法
),就看父类有没有这个属性
(方法
)(如果父类有该属性
(方法
),并可以访问,就返回信息…) - 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该
属性
(方法
)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误
- 首先看子类是否有该
- 在
4.3 super关键字
-
基本介绍
注意:super
不是一个对象引用,super
是一个指示java编译器调用父类实例域
的特殊关键字
-
super的细节
public class A{public void say(){System.out.println("A say~~");}
}public class B extends A{public void test(){// say();// this.say();super.say();}
}
- 在B的方法中调用
say()
(与this.say()
等同)的执行流程如下:- 首先看子类是否有该
属性
(方法
) - 如果子类有这个
属性
(方法
),并可以访问,则返回信息 - 如果子类没有这个
属性
(方法
),就看父类有没有这个属性
(方法
)(如果父类有该属性
(方法
),并可以访问,就返回信息…) - 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该
属性
(方法
)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误
注意:使用super.say()
会跳过上述第一步,直接从其父类开始查找
- 首先看子类是否有该
4.4 super与this的比较
4.5 方法重写/覆盖(override)
-
基本介绍
-
方法重写注意事项和使用细节
4.6 方法重写与重载比较
4.7 多态
4.7.1 基本介绍
注意 编译类型
与 运行类型
的概念
4.7.2 多态注意事项和细节讨论
- 调用方法使用
运行类型
,直接访问属性使用编译类型
public class Animal{public void eat(){System.out.println("...");}
}class Cat extends Animal{public void eat(){ // 方法重写System.out.println("吃鱼"); }
}class Dog extends Animal{public void eat(){ // 方法重写System.out.println("吃骨头"); }
}
public class Test{public static void main(String[] args){Animal animal = new Cat(); // 父类的引用指向了子类的实例// 可以调用父类中的所有成员(需要遵守访问权限)// 但是不能调用子类的特有的成员 (因为需要通过java的编译)// 因为在编译阶段,能调用哪些成员,是由编译类型来决定的// 最终的运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法// 然后调用,规则和我们前面讲的方法调用规则一致animal.eat(); // 调用重写的实现}
}
- 注
null
数据也可以使用instanceof
,其结果为false
public class Test{public static void main(String[] args){BB bb = new BB();System.out.println(bb instanceof BB); // trueSystem.out.println(bb instanceof AA); // true// aa的编译类型是AA,运行类型是BBAA aa = new BB();System.out.println(aa.n); // "a",说明访问的是编译类型对应的属性值System.out.println(aa instanceof AA); // trueSystem.out.println(aa instanceof BB); // true,说明 instanceof 判断的是aa的运行类型是否是BB}
}class AA{String n = 'a';
}class BB extends AA{String n = 'b';
}
4.7.3 java的动态绑定机制(非常非常重要)
- 当调用对象
方法
的时候,该方法会和该对象的内存地址/运行类型
绑定 - 当调用对象
属性
时,没有动态绑定机制
,哪里声明,哪里使用
public class Test{public static void main(String[] args){A a = new B(); // 向上转型// 动态绑定机制: // (1)调用 B 类继承的sum方法(sum() 与 B 的实例绑定,这里 this --> new B()); // (2)其中getI() (同this.getI())则调用B中重写的方法; // (3)B中的getI()方法中的 i (同this.i)没有动态绑定机制则返回B的成员变量ISystem.out.println(a.sum()); // 30// 动态绑定机制: // (1)调用 B 类继承的sum1方法(sum1() 与 B 的实例绑定,这里 this --> new B()); // (3)其中的 i (同this.i)没有动态绑定机制则返回A的成员变量ISystem.out.println(a.sum1()); // 20}
}class A{ // 父类public int i = 10;public int sum(){return getI() + 10;}public int sum1(){return i + 10;}public int getI(){return i;}
}class B{ // 子类public int i = 20;public int getI(){return i;}
}
4.7.4 多态的应用
五、Object类详解
5.1 equals方法
Object
类的equals
方法实现的是判断是否是同一个对象
// 自定义equals方法
public class Person{private String name;private int age;private char gender;public Person(String name, int age, char gender){this.name = name;this.age = age;this.gender = gender;}public boolean equals(Obejct obj){if (obj == this){return true;}if(obj instanceof Person){Person pObj = (Person) obj ;return this.name.equals(pObj .name) && this.age == pObj.age && this.gender == pObj.gender;}return false;} }
5.2 hashCode方法
5.3 toString()方法
5.4 finalize方法
六、断点调试
七、细节知识
7.1 访问修饰符
成员变量
和方法
可以被:public
、protected
、默认
、private
修饰- 类只能被:
public
和默认
修饰
注:上述多个访问范围之间是或的关系(如:protected修饰的属性或方法可以被 同类
或 同包
或 子类
访问)。另外 同包
指的是 完全相同的包路径
(子包路径不算相同)
7.2 继承的细节
- 注意第6点,使用了
this()
后则编译器不会默认添加一个super()
7.3 继承的本质分析(内存分析,重要)
public class ExtendsTest{public static void main(String[] args){Son son = new son(); // 内存的布局}
}class GrandPa{String name = "大头爷爷";String hobby = "旅游";
}class Father extends GrandPa{String name = "大头爸爸";int age = 39;
}class Son extends Father{String name = "大头儿子";
}
- 执行流程:
- 在
方法区
中加载类信息
,顺序由继承关系决定(Object
-->GrandPa
-->Father
-->Son
)并建立类之间的关系 - 在堆中创建Son的实例,按
继承关系
创建属性
并初始化
(各父类中的变量会存储在独立的二级堆空间
中) - 将Son实例的引用赋值给
main方法栈
中的son引用变量
- 若使用son调用
属性
或方法
,则遵守以下原则:- 首先看子类是否有该
属性
(方法
) - 如果子类有这个
属性
(方法
),并可以访问,则返回信息 - 如果子类没有这个
属性
(方法
),就看父类有没有这个属性
(方法
)(如果父类有该属性
(方法
),并可以访问,就返回信息…) - 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该
属性
(方法
)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误
- 首先看子类是否有该
- 在
7.4 super细节
注意:super
不是一个对象引用(不能赋值给引用变量),super
是一个指示java编译器调用父类实例域
的特殊关键字
public class A{public void say(){System.out.println("A say~~");}
}public class B extends A{public void test(){// say();// this.say();super.say();}
}
- 在B的方法中调用
say()
(与this.say()
等同)的执行流程如下:- 首先看子类是否有该
属性
(方法
) - 如果子类有这个
属性
(方法
),并可以访问,则返回信息 - 如果子类没有这个
属性
(方法
),就看父类有没有这个属性
(方法
)(如果父类有该属性
(方法
),并可以访问,就返回信息…) - 如果父类没有就按照(3)的规则,继续找上级父类,直到Object。注意:如果某一父类中有该
属性
(方法
)但由于访问修饰符限制(如:private)无法直接访问,则java编译器会停止向其父类寻找,直接返回无法访问的编译错误
注意:使用super.say()
会跳过上述第一步,直接从其父类开始查找
- 首先看子类是否有该
7.5 方法重写的细节
7.6 多态的理解
- 注意
编译类型
与运行类型
的概念 - 调用方法使用
运行类型
,直接访问属性使用编译类型
public class Animal{public void eat(){System.out.println("...");}
}class Cat extends Animal{public void eat(){ // 方法重写System.out.println("吃鱼"); }
}class Dog extends Animal{public void eat(){ // 方法重写System.out.println("吃骨头"); }
}
public class Test{public static void main(String[] args){Animal animal = new Cat(); // 父类的引用指向了子类的实例// 可以调用父类中的所有成员(需要遵守访问权限)// 但是不能调用子类的特有的成员 (因为需要通过java的编译)// 因为在编译阶段,能调用哪些成员,是由编译类型来决定的// 最终的运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法// 然后调用,规则和我们前面讲的方法调用规则一致animal.eat(); // 调用重写的实现}
}
public class Test{public static void main(String[] args){BB bb = new BB();System.out.println(bb instanceof BB); // trueSystem.out.println(bb instanceof AA); // true// aa的编译类型是AA,运行类型是BBAA aa = new BB();System.out.println(aa.n); // "a",说明访问的是编译类型对应的属性值System.out.println(aa instanceof AA); // trueSystem.out.println(aa instanceof BB); // true,说明 instanceof 判断的是aa的运行类型是否是BB}
}class AA{String n = 'a';
}class BB extends AA{String n = 'b';
}
7.7 java的动态绑定机制(非常非常重要)
- 当调用对象
方法
的时候,该方法会和该对象的内存地址/运行类型
绑定 - 当调用对象
属性
时,没有动态绑定机制
,哪里声明,哪里使用
public class Test{public static void main(String[] args){A a = new B(); // 向上转型// 动态绑定机制: // (1)调用 B 类继承的sum方法(sum() 与 B 的实例绑定,这里 this --> new B()); // (2)其中getI() (同this.getI())则调用B中重写的方法; // (3)B中的getI()方法中的 i (同this.i)没有动态绑定机制则返回B的成员变量ISystem.out.println(a.sum()); // 30// 动态绑定机制: // (1)调用 B 类继承的sum1方法(sum1() 与 B 的实例绑定,这里 this --> new B()); // (3)其中的 i (同this.i)没有动态绑定机制则返回A的成员变量ISystem.out.println(a.sum1()); // 20}
}class A{ // 父类public int i = 10;public int sum(){return getI() + 10;}public int sum1(){return i + 10;}public int getI(){return i;}
}class B{ // 子类public int i = 20;public int getI(){return i;}
}
这篇关于七、面向对象编程(中级)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!