2.5 面向对象OOP(Object Oriented Programming)
目录
1. 初识面向对象
-
面向对象编程:Object Oriented Programming,OOP
-
面向对象编程的本质就是:以类的形式组织代码,以对象的形式封装数据
-
抽象
-
三大特性:
- 继承
- 封装
- 多态
-
从认识论的角度考虑,是先有对象后有类。
类,是抽象的;对象,是具体的。
-
从代码运行的角度考虑,是先有类后有对象。类是对象的模板。
2. 方法的回顾与加深
-
方法的定义
-
修饰符
-
返回类型
-
break(1.跳出switch;2.终止循环)和return(结束方法。返回结果。可以为空)的区别
-
方法名(注意规范,见名知义)
-
参数列表(参数类型,参数名)
-
异常抛出
public void readFile(String file) throws IOException{ }
-
-
方法的调用:递归
-
静态方法
-
非静态方法
main方法
package com.kuang.objectOrientedProgramming; public class StaticMethod 11{ //1.静态方法static:直接Student.say调用 //2.非静态方法:实例化new 对象类型 对象名 = 对象值 public static void main(String[] args) { Student student = new Student(); student.say(); //形式参数和实际参数的类型要对应一致 System.out.println(student.add(12,3)); a(); } // static:和类一起加载,直接使用 public static void a(){ b(); } //无static:实例化后才能使用 public static void b(){ System.out.println("静态方法!"); } }Student类
package com.kuang.objectOrientedProgramming; public class Student { public void say(){ //1.静态方法static:直接Student.say调用 //2.非静态方法qZ //对象类型 对象名 = 对象值 System.out.println("学生说话了"); } //形式参数和实际参数的类型要对应一致 public int add(int a, int b){ return a+b; } } -
形参和实参(形参和实参类型要对应一致)
precedent 先例
-
值传递和引用传递
package com.kuang.objectOrientedProgramming; //引用传递,本质还是值传递 public class ValueRecedent { public static void main(String[] args) { int a = 1; System.out.println(a); ValueRecedent.change(a); System.out.println(a); //输出结果仍未1,说明是值传递。用Debug一步步跟进 Person person = new Person(); System.out.println(person.name); ValueRecedent.change(person); System.out.println(person.name); //输出结果由null->Shiki } public static void change(int a){ a = 10; } //change方法重载,注意形参类型为Person类的person,因此实参不能是一个具体属性person.name public static void change(Person person){ //person是一个对象,指向的是--->Person person = new Person(),这hi是一个具体的人,一定可以改变 person.name = "Shiki" ; } } //一个类中可以有多个class,但是只能有一个public class class Person{ String name;//不初始化,默认值为null } -
this关键字(继承里面再讲)
-
3. 对象的创建方法
-
类和对象的关系
- 类是一种抽象的数据类型,它是对某一类事物的整体描述/定义,但是不能个代表某一个具体的事物
- 对象是抽象概念的具体实例
-
创建与初始化对象
-
使用new关键字创建对象
package com.kuang.objectOrientedProgramming.application; //一个项目之应该只有一个main方法,且越简单越好 public class Application { public static void main(String[] args) { Student xiaoming = new Student(); Student xiaohong = new Student(); //类实例化后会返回自己的一个对象 //Student对象就是Student 的一个具体实例 xiaoming.name = "小明"; xiaohong.name = "小红"; xiaoming.age = 13; xiaohong.age = 23; } }package com.kuang.objectOrientedProgramming.application; public class Student { //一个类里面只有属性和方法 //1. 属性 String name;//null int age;//0 // 2.方法 public void study(){ //this表示当前类 System.out.println(this.name+"在学习"); } } -
使用new关键字的时候,除了分配内存空间外,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用
通过Project Structure 查看.class字节码文件


-
类中的构造器也称构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- *必须没有返回类型,也没有void
两个作用:
- new的本质是在调用构造方法constructor
- 初始化对象的值
package com.kuang.objectOrientedProgramming.application; //一个项目之应该zhi有一个main方法 public class Application { public static void main(String[] args) { Person person = new Person("Nothing");//new Person() ALT+回车 System.out.println(person.name); } } /* Student xiaoming = new Student(); Student xiaohong = new Student(); //类实例化后会生产自己的一个对象 //Student对象就是Student 的一个具体实例 xiaoming.name = "小明"; xiaohong.name = "小红"; xiaoming.age = 13; xiaohong.age = 23; */package com.kuang.objectOrientedProgramming.application; //编译成功后去查看.class文件 public class Person { //一个类即使什么都不写,它也会存在一个方法。 //显示的定义构造器 //类名相同且无参数。 String name; //实例化初始值 /* 1. 使用new关键字,本质是在调用构造器(无参构造) 2. (有参构造)一旦定义了有参构造,无参必须 显示定义,否则报错 */ public Person(){ this.name = "Shiki"; } public Person(String name){ this.name = name;//this. 表示当前类 //构造器快捷键constructor ALT + insert //有参构造和无参构造就是方法重载! } }关于快速创建构造方法的快捷键AlT +Insert


-
-
构造器必须要掌握
-
根据练习回想一下Java内存
package com.kuang.objectOrientedProgramming.anmialBuild; public class Application { public static void main(String[] args) { Pet dog = new Pet(); dog.name = "baozi"; dog.age = 1 ; dog.shout(); System.out.println(dog.age); System.out.println(dog.name); } }package com.kuang.objectOrientedProgramming.anmialBuild; public class Pet { public String name; public int age; public void shout(){ System.out.println("wangwangwang~~~"); } }结合这两张图



属性的多种叫法:字段(field), 成员变量
4. **Java的三大特性:封装 继承 多态 **
-
封装
封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
程序设计目标:高内聚,低耦合。
package com.kuang.objectOrientedProgramming.fengzhuang; public class App { public static void main(String[] args) { Student Shiki = new Student(); //不能直接Shiki.age,因为属性私有。 //用一些public的Get/set方法 Shiki.setName("SK214"); Shiki.setAge(21); Shiki.setSex('f'); System.out.println(Shiki.getName()); System.out.println(Shiki.getAge()); System.out.println(Shiki.getSex()); } }package com.kuang.objectOrientedProgramming.fengzhuang; public class Student { private String name; private int age; private char sex; //get获取,set设置 /* 封装的意义 1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 4.系统的可维护性增加了 */ public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(this.age > 120 ||this.age <0 ) System.out.println("Wrong Input!!!!"); else this.age = age; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } } -
继承
extends 拓展
类与类之间的关系:

继承关键字 :extends
称呼:父类/基类 -->子类/派生类
-
Object类:在Java中,所有的类都默认直接或者间接的继承Object类
-
super
- super调用父类的构造方法,且必须在第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法!
-
super与this的区别
- 代表的对象不同:
- this:本身调用者这个对象
- super:代表父亲对象的应用
- 前提:
- this:没有继承也能使用
- super:只有在继承条件下才能使用
- 构造方法:
- this:本类的构造
- super:父类的构造
package com.kuang.objectOrientedProgramming.extendss; public class App { public static void main(String[] args) { Students students = new Students(); //students.sleep(); //子类继承了父类的所有方法 //System.out.println(students.money); //students.test("WeiNa"); // students.test1(); } }package com.kuang.objectOrientedProgramming.extendss; public class Person { /** * 4种修饰符 * 1.public * 2.protected * 3.default 不写默认就是这个 * 4.private */ public Person(){ System.out.println("Person无参构造器执行了"); } int money = 100_000_000;//可以使用下划线来分割数字,便于认识 protected String name = "HuangYe"; public void sleep(){ System.out.println("It's time to go to bed."); } public void print(){ System.out.println("Person"); } //CTRL + H 查看继承树的快捷键。 //在Java中,所有的类都默认直接或者间接的继承Object类 }package com.kuang.objectOrientedProgramming.extendss; public class Students extends Person{ public Students(){//无参构造器修饰符为public //new一个子类时,隐藏操作是先调用父类的无参构造 super();//这一句调用父类无参构造可写可不写,但是一定要放在第一句,否则报错 System.out.println("Students无参构造器执行了"); } private String name = "orange"; public void test(String name){ System.out.println(name); //WeiNa System.out.println(this.name); //Orange System.out.println(super.name); //HuangYe } public void test1(){ print(); //Student this.print(); //Student super.print(); //Person } public void print(){ System.out.println("Student"); } } - 代表的对象不同:
-
方法重写(不是方法重载,重载是同名但是参数不同)
Java是单继承,不是多继承!(可以多个儿子,但是不能多个父亲)
DP Dynamic Process 动态规划
-
需要有继承关系,子类重写父类的方法
-
参数列表列表必须相同
-
修饰符:范围可以扩大,public > protected >default > private
-
抛出的异常:可以被缩小,但不能放大
classNotFoundException -> Exception
重写子类的方法和父类的必须一致,方法体不同。
为什么需要重写:
-
父类的功能,对于子类来说过多或者过少
Alt + Insert :override
package com.kuang.objectOrientedProgramming.overrideee;
public class App {
public static void main(String[] args) {
A a = new A();
a.test();//输出A的test
// B 是爹,父类的引用指向了子类
//方法的调用值和左边,也就是定义的数据类型有关
B b = new A();//输出B的test
b.test();
}
}
package com.kuang.objectOrientedProgramming.overrideee;
//重写都是方法的重写和属性无关
public class B {
public static void test(){
System.out.println("B的test");
}
}
package com.kuang.objectOrientedProgramming.overrideee;
public class A extends B {
// public void test(){
// System.out.println("A的test");
// }
//Override 重写
//@Override//注解,有注释的功能
public static void test() {
//super.test();
System.out.println("A的test");
}
}
带static

不带static

- 多态
多态:同一方法根据发送对象的不同而采取的多种不同的行为方式,多态让程序变得更灵活
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多

qualifier 限定词,限定语

Student s1 = new Student();
引用类型 变量名 = new关键字 实际类型
多态的注意事项:
- 多态是方法的多态,属性****没有多态
- 父类和子类有联系。不相关的类型会异常,classCastException
- 存在条件,继承关系,方法需要重写,父类指向子类对象。Father f1 = new Son()
- static 方法,不能重写。属于类,他不属于实例
- final 常量
- private 方法
package com.kuang.objectOrientedProgramming.manyStage;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型(指右边Student())是可以确定的
//Student s1 = new Student();
//引用类型 变量名 = new关键字 实际类型
//对象的引用类型(左侧)就不确定了:例如下面第2,3条,父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
//对象能执行那些类型,主要看左边的引用类型,和右边的实际类型关系不大
s2.run();//子类重写了父类的方法,执行子类的方法;子类没有重写,执行父类的方法
//子类型可以调用自己的或者父亲的方法
((Student) s2).eat(); //父类型可以指向子类,但是不能调用子类独有的方法
//(类型)高转低需要类型强制转换
}
}
package com.kuang.objectOrientedProgramming.manyStage;
public class Person {
public void run(){
System.out.println("run");
}
}
package com.kuang.objectOrientedProgramming.manyStage;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
类型转换在基本数据类型那里就是:高容量转低容量
在类和方法这里就是:父类转子类
instanceof (类型转换) 引用类型,判断一个对象是什么类型
先用instanceof 判断类型是否相似,然后再强制转换
false和编译不通过不一样
编译看左,运行看右
//左边的引用类型决定能否编译,右边的实际类型决定是true还是false,
//编译看左,运行看右
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);//false
//----------------------------------------------------------
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);//报错,Person和String是Object下的同级关系
//----------------------------------------------------------
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);//报错
//----------------------------------------------------------

多态出现的条件
- 父类引用指向了子类的对象
- 把子类转换为父类,向上转型
- 把父类转换为子类,向下转型
- 方便方法的调用,减少new的代码
final 关键字后不能继承,断子绝孙
5. 抽象类以及接口
抽象类
-
abstract** 修饰符可以用来修饰方法,也可以修饰类。如果修饰方法,就是抽象方法。如果修饰类,就是抽象类。
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定为抽象类。
-
抽象类,不能使用new键字来创建对象,它是用来让子类继承的
-
抽象方法,只用方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,那么就必须要实现抽象类没有 实现的抽象方法,否则该孩子也声明为抽象类。
implement 是什么生效,贯彻执行;n. 工具器具用具
package com.kuang.objectOrientedProgramming.staticcc;
public abstract class Action {
//约束,有人帮我们实现
public Action(){//无参构造方法
System.out.println("仿生人会梦见电子羊吗?");
}
public abstract void doSomething();// 抽象类中的抽象方法
//abstract,抽象方法,只有方法名字,没有方法体来实现,子类继承必须要重写
//1. 不能new这个抽象类,只能靠子类去实现它;约束!
//2, 抽象类中可以写普通方法
//思考:1.抽象类不能new,那么他能存在构造器吗?neng
// 2.抽象类存在的意义 抽象出来~~~ 提高代码的开发效率
}
package com.kuang.objectOrientedProgramming.staticcc;
import com.kuang.objectOrientedProgramming.overrideee.A;
public class Abandon extends Action{//abstract 抽象类;extends 是单继承,但接口implement可以实现多继承
@Override// 抽象方法的重写
public void doSomething() {
}
}
抽象类中可以有构造方法
class AbstractDemo01 {
public static void main(String[] args) {
B b = new B("哦");
B b2 = new B();
}
}
abstract class A {
public A() {
System.out.println("抽象类A的构造方法");
}
}
class B extends A {
public B() { }
public B(String name) {
super(); //没有这句代码内部也会调用,默认隐式加上这句
System.out.println(name);
}
}
接口
- 区别与联系’
- 普通类:只有具体细实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范!没有实现的方法!约束和实现相分离
- 关键字interface,接口的本质是契约
- OO的精髓,是对抽象的抽象,最能体现这一点的就是接口
- 作用:
- 约束
- 定义一些方法,让不同的人实现
- 方法都是public abstract
- 属性都是public static final
- 接口中没有构造方法,不可以被实例化
- implements可以实现多个接口
- 总结博客
package com.kuang.objectOrientedProgramming.interfaceee;
public interface UserService { //接口关键字就是interface
public abstract void run();
//接口中的属性,常量
public static final int AGE = 99;
//接口默认的方法都是,public abstract 是灰色的,即默认是公共抽象,可以省去
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package com.kuang.objectOrientedProgramming.interfaceee;
//类可以实现implements接口,常见实现类的后缀就是--Impl,关键字implements
public class UserServiceImpl implements UserService,TimeService{
@Override
public void timer() {
}
@Override
public void run() {
}
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}//逗号分隔,实现多继承
}
6. 内部类
匿名类,没有名字初始化类,不用将实例保存到变量中
new apple().eat()
package com.kuang.objectOrientedProgramming.OuterClass;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类outer按照顺序来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
package com.kuang.objectOrientedProgramming.OuterClass;
public class Outer {
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
//类里面再写一个类。内部类
public class Inner{
public void in(){
System.out.println("这是内部类方法");
}
public void getID(){
System.out.println(id);//内部类可以get到外部类的私有属性
//如果内部类Inner加上static修饰,getid就报错了。因为先实现static
}
}
}

浙公网安备 33010602011771号