06 面向对象
01 什么是面向对象
面向对象的本质以类的方式组织代码,以对象的组织封装数据
三大特性:封装,继承,多态(顺序固定)
02 回顾方法的定义
package com.kuang.oop.demo01;
import java.io.IOError;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) {
System.out.println();
}
/*
修饰符 返回值类型 方法名(...){
//方法体
return 返回值;
}
*/
//break停止switch和跳出循环
//return结束方法,返回一个结果
//方法名要见名知意
// 参数列表(参数类型,参数名)..
// 抛出异常
public String sayHello(){
return "hello,world";
}
public void print(){
return;
}
public int max(int a,int b){
return a>b? a:b; //三元运算符
}
public void readFile(String file) throws IOException{
}
}
03 回顾方法的调用
- 静态方法,通过类名直接调用
- 动态方法,需要实例化(new)后再调用
也可以改为:
Demo02 demo02 = new Demo02();
demo02.say();
静态方法的加载
非静态方法可以互相调用,这里死循环了不用在意
同为静态方法也可以相互调用
但在a方法为静态,b方法为非静态就无法调用了
因为静态方法与类同时加载,而非静态方法在类实例化后才存在,时间线不同所以不可调用
值传递与引用传递
值传递:
在调用change()方法后改变的是形式参数a的值,并没有返回值,所以main方法中的a的值不变,仍为1。
引用传递
package com.kuang.oop.demo01;
//引用传递:对象,本质还是值传递
//类似于指针传递
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
Demo05.change(person);
System.out.println(person.name);
}
public static void change(Person person){
//person是一个对象,指向的是--->Person person = new Person();这是一个具体的人,可以改变属性
person.name = "好哥哥";
}
}
class Person{
String name;
}
类似于C语言中的指针引用传递。
04 类与对象的创建
- 对象就是类的具体实例化。
- 使用new关键字创建对象
- 面向对象编程的本质就是以类的方式组织代码,以对象的方式封装数据。
05 构造器详解
-使用new关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象进行默认的初始化和对类中构造器的调用。
构造器必须掌握
- 建立一个类Teacher,在测试类中建立Teacher类对象。即使Teacher类中什么也没写也可以调用。
- 通过java文件编译后生成.class文件查看:
Teacher类中有默认的构造方法。
public class Person {
//显示的定义和构造
String name;
int age;
//alt+insert
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
/*
public static void main(String[] args) {
//实例化一个对象
Person person = new Person("wsh",20);
System.out.println(person.name);
}
构造器:
1和类名相同
2没有返回值
作用:
1new本质在调用构造方法
2初始化对象的值
注意点:
1定义有参构造方法后,若要调用无参构造方法,必须显示定义
Alt+insert
this表示当前类
*/
06 创建对象内存分析(便于理解,真正的内存很复杂)
首先加载测试类Application,
07 简单小结类与对象
1.类与对象
类是一个模板:抽象,对象是一个具体的实例
2.方法
定义、调用
3.对应的引用
引用类型: 基本类型(8)
对象是通过引用来操作的:栈--》堆
4.属性:字段Field 成员变量
默认初始化:
数字:0 0.0
char: u0000
boolean:false
引用:null
修饰符 属性类型 属性名 = 属性值!
5.对象的创建和使用
- 必须使用new关键字创建对象,构造器 Person kuangshen = new Person();
- 对象的属性 kuangshen.name
- 对象的方法 kuangshen.sleep()
6.类
静态的属性 属性
动态的行为 方法
封装、继承、多态
08封装详解
该露的露,该藏的藏
“高内聚,低耦合”,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合,仅暴露少量的方法给外部使用。
对于代码来说,就是属性私有,get/set
package com.kuang.oop.demo04;
/*
封装
1、提高代码的安全性
2、隐藏代码实现细节
3、统一接口get/set
4、系统可维护
记住这句话:属性私有,get/set
*/
public class Student {
//封装大多数是对于属性来的
//类 private 私有 属性私有
public 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生成get/set方法
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<120||age>0)
this.age = age;
else
this.age=3;
}
}
09 什么是继承
- extends的意思是“扩展”,子类是父类的继承
- java类中只有单继承,没有多继承-----儿子可以有多个,爹只能有一个
- 继承是类与类之间的关系,除此之外,还有依赖,组合,聚合等。
- 继承关系的两个类,一个为子类,一个为父类,子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上应该有“is a”的关系。
建立一个包demo05,存放三个类,Person,Student类。
package com.kuang.oop.demo05;
//java中所有的类都默认直接或间接继承了Object类
public class Person /*extends Object*/{
//public
//protected
//default
//private
private int money = 10_0000_0000;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void run(){
System.out.println("说了一句话");
}
}
这里的Person类为父类,Object类为所有类的父类(基类)
package com.kuang.oop.demo05;
//学生 is 人
//子类继承了父类,就会拥有父类的全部方法
public class Student extends Person{
//CTRL+H 继承树
}
Student类继承了Person类,在建立学生对象后即可调用父类的方法run()
- ctrl+h 可以在右边查看继承树
- 在测试类中建立Student类的对象,点 一下可以查看可调用方法
上方红框内为Person类的方法,下方框内为Object类的方法。
10 Super详解
//父类 Person类
public class Person /*extends Object*/{
protected String name = "kuangshen";
public void print(){
System.out.println("Person");
}
}
//Student类
package com.kuang.oop.demo05;
//学生 is 人
//子类继承了父类,就会拥有父类的全部方法
public class Student extends Person{
//CTRL+H 继承树
private String name = "qinjiang";
public void test(String name){
System.out.println(name); //秦疆
System.out.println(this.name); //qinjiang
System.out.println(super.name);//kuangshen
}
}
输出的三个结果分别为方法的参数,当前类的属性name,父类的属性name
同样的对于方法,
package com.kuang.oop.demo05;
//学生 is 人
//子类继承了父类,就会拥有父类的全部方法
public class Student extends Person{
//CTRL+H 继承树
private String name = "qinjiang";
public void print(){
System.out.println("Student");
}
public void test1(){
print(); //Student
this.print(); //Student
super.print(); //Person
}
}
显示定义Person类和Student类的构造方法,
只建立一个Student对象会发现,Person类和Student类的构造方法都被执行了。
隐藏代码:调用了父类的无参构造
调用父类的构造器,必须要在子类构造器的第一行
super注意点:
1、super调用父类的构造方法,必须在构造方法的第一个
2、super必须出现在子类的方法或者构造方法中!
3、super和this不能同时调用构造方法
Vs this:
代表的对象不同:
this: 本身调用者这个对象
super: 代表父类对象的引用
前提:
this:没有继承也可以使用
super:只有在继承条件下才可以使用
构造方法:
this(): 本类的构造
super(): 父类的构造
11 方法重写
首先定义两个静态方法,结果为AB
非静态方法时,结果都为A
即b是A new 出来的对象,因此调用的是A的方法。
因为静态方法是类的方法,而非静态是对象的方法。
有static时,b调用了B类的方法,因为b是用b类定义的
没有static时,b调用的是对象的方法,而b是用A类new的
区别:静态与非静态 重写与静态方法没有任何关系,静态方法在类加载时就已经出来了
主要是和非静态方法有关。
重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大,但是不能缩小private->protected->Deafault->public
4.抛出的异常:范围,可以被缩小,但不能扩大;ClassNotFoundException -->exception(大)
重写:子类的方法和父类必须要一致,方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足
初期可能不太理解,没有关系,也可以死记硬背一些,在后面的使用中去慢慢理解。
12 什么是多态
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
-
一个对象的实际类型是确定的,但可以指向的引用的类型很多。
-
多态存在的条件
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象
//Person类
public class Person {
public void run(){
System.out.println("run");
}
}
//Student类
public class Student extends Person{
}
///测试类
package com.kuang.oop;
import com.kuang.oop.demo06.Person;
import com.kuang.oop.demo06.Student;
//静态与非静态的方法区别很大!
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了,父类的引用指向子类
Student s1 = new Student();
//Person父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run();
}
}
执行结果为:
run
子类Student继承父类方法,则调用输出run。
public class Student extends Person{
@Override
public void run() {
System.out.println("son.run");
}
}
子类Student重写run方法,则优先调用子类方法,输出son.run。
public class Student extends Person{
@Override
public void run() {
System.out.println("son.run");
}
public void eat(){
System.out.println("eat");
}
}
在子类中添加eat方法,发现s2不可调用eat方法,因为父类不可调用子类独有的方法。
father f1 = new son();
意思就是new了一个子类的对象,子类的对象里面有继承父类的方法。
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类有联系 类型转换异常ClassCastException
3.存在条件: 继承关系,方法需要重写,父类的引用指向子类对象!
不可实现多态:
1.static 方法,属于类,不属于实例
2.final常量
3.private方法
instance of 和类型转换
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
package com.kuang.oop;
import com.kuang.oop.demo06.Person;
import com.kuang.oop.demo06.Student;
import com.kuang.oop.demo06.Teacher;
//instanceof 是 Java 的保留关键字。
// 它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
public class Application {
public static void main(String[] args) {
//Object > String
//Object > Person > Teacher
//Object >Person> Student
Object ob = new Student();
System.out.println(ob instanceof Student);
System.out.println(ob instanceof Person);
System.out.println(ob instanceof Object);
System.out.println(ob instanceof Teacher);
System.out.println(ob instanceof String);
System.out.println("=======================");
Person person = new Person();
System.out.println(person instanceof Student);
System.out.println(person instanceof Person);
System.out.println(person instanceof Object);
System.out.println(person instanceof Teacher);
//System.out.println(person instanceof String); //编译报错
}
}