P60 面向对象编程(OOP)
面向对象编程(Object-Oriented Programming,OOP)
定义
本质就是:以类的方式组织代码,以对象的组织(封装)数据
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理
三大特性
- 封装
- 继承
- 多态
P62 方法的调用
静态方法和非静态方法
//Demo02.java
package com.oop.demo01;
public class Demo02{
public static void main(String[] args){
Student.say();//静态方法
Student student = new Student();//非静态方法
student.say();
}
}
//Student.java
// 非静态方法
package com.oop.demo01;
public class Student{
public static void say(){
System.out.println("学生说话了");
}
}
//Student.java
//非静态方法
package com.oop.demo01;
public class Student{
public void say(){
System.out.println("学生说话了");
}
}
static是和类一起加载的,比如说
public static void a(){
b();//这里就会报错,因为static和类一起加载的,而b是在类实例化的时候才会存在的,static可以调static,都没有static也可以调
}
public void b(){
}
形参和实参
值传递和引用传递
java里都是值传递
引用传递:对象,本质还是值传递
P63 类与对象的创建
使用new关键字创建对象,除了分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
//Student.java
package com.oop.demo02;
//学生类
public class Student {
//属性:字段
String name;//默认值是null
int age;//默认值是0
//方法
public void study(){
System.out.println(this.name+"学生在学习");
}
}
//Application.java
package com.oop.demo02;
//一个项目应该只存一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象!
//student对象就是一个Student类的具体实例
Student xiaoming = new Student();
xiaoming.name = "小明";//给类的属性赋值
xiaoming.age = 3;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
P64 构造器详解(类似C++构造函数)
类中的构造器也成为构造方法,是在进行创建对象的时候必须要调用的,并且构造器有以下两个特点
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
作用
- new本质在调用构造方法
- 初始化对象的值
注意点
- 定义有参数构造之后,如果想使用无参构造,显示的定义一个无参的构造
IDEA快捷键alt+insert
//Person.java
package com.oop.demo02;
public class Person {
//一个类即使声明都不写,它也会存在一个方法
//public Person(){};
String name;
//实例化初始值
//显式的定义构造器
//1.使用new关键字,本质是在调用构造器
//无参构造
public Person(){
this.name = "qingjiang";
}
//有参构造
public Person(String name){
this.name = name;
}
}
//Application.java
package com.oop.demo02;
//一个项目应该只存一个main方法
public class Application {
public static void main(String[] args) {
//new 实例化了一个对象
Person person = new Person("1");
System.out.println(person.name);
}
}
P65 创建对象内存分析
创建对象内存分析图
查看狂神的本节视频
P69 继承
public class Student extends Person{//学生类继承了人类
}
子类继承了父类,就会拥有父类的全部方法
-
私有的(private)东西是无法继承的
//public
//protected
//default
//private
在java中,所有的类,都会默认直接或简洁继承Object类
- java中类只有单继承,没有多继承(一个儿子只能有一个爸爸,但一个爸爸可以有多个儿子)
P69 Super详解
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或构造方法中!
- super和this不能同时调用构造方法!
对比 this:
-
代表的对象不同
- this:本身调用这个对象
- super:代表父类对象的引用
-
前提不同
- this:没有继承也可以使用
- super:只能在继承条件下才可以使用
-
构造方法
- this:本类的构造
- super:父类的构造
P70 方法重写
//Application.java
package com.oop.demo05;
public class Application {
public static void main(String[] args) {
//静态方法和非静态方法区别很大
//静态方法:方法的调用只和左边,定义的数据类型有关
//非静态方法:重写,关键词只能是public不能是private
A a = new A();
a.test();//A
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();//如果是static的方法那么就输出B类的test,如果是重写的非静态方法,那么就输出A类的test
}
}
//A.java
package com.oop.demo05;
public class A extends B{
//Override 重写
@Override //注释:有功能的注释!
public void test(){//如果写成静态,在A和B里都写成public static void test(){}
System.out.println("A.test()");
}
}
//B.java
package com.oop.demo05;
//重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B.test()");
}
}
重写:需要有继承关系,子类重写父类的方法!(重写只针对方法)
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大:public>Protected>Default>private
- 抛出的异常:范围,可以被缩小,但不能扩大: ClassNotFoundException --->Exception(大)
重写,子类的方法和父类必须要一致,方法体不同!
为什么需要重写
- 父类的功能,子类不一定需要,或者不一定满足!
Alt+Insert:override
P71 多态
//不可运行的代码
//Person是Student的父类
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
//Person父类型,可以指向子类,但是不能调用子类独有的方法
Persion s2 = new Student();//父类的引用指向子类
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.eat();//如果子类重写了父类的方法,则执行子类的方法,无则执行父类的方法
s1.eat();
}
}
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系。如上例中,不能把String类型转换成Person类型,否则会出现类型转换异常!ClassCastException!
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
- 无法重写的方法
- static 方法,属于类,它不属于实例
- final 常量
- private方法
P72 instanceof和类型转换
instanceof
//编译是否通过看引用类型(左边),结果对错看实际类型(右边)
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 Teacher);//false
System.out.println(object instanceof String);//flase
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 Teacher);//false
System.out.println(person instanceof String);//编译报错!
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 Teacher);//编译报错
System.out.println(student instanceof String);//编译报错
类型转换
父类>子类,
- 父类引用指向子类的对象
- 把子类转换为父类,称为向上转型,可以直接转但是会丢失子类特有的方法;
- 把父类转换为子类,称为向下转型,需要强制转换
- 意义是方便方法的调用,减少重复的代码