Java 面向对象编程

面向对象编程

1. 初识面向对象

1.1 面向过程(具体的)

  • 步骤清晰简单,第一步做什么、第二部做什么........

  • 适合处理一些较为简单的问题

1.2 面向对象(OOP,抽象的)

  • 分类的思维模式,思考问题首先会 解决问题需要哪些分类,然后 对这些分类进行单独思考。最后 对某个分类下的细节进行 面向过程的思索。

  • 适合处理复杂问题

对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用 面向对象 的思路来分析整个系统。但具体到微观操作,仍需要面向过程的思路去处理。

1.3 什么是面向对象

  • 面向对象编程的本质:以类的方式组织代码,以对象的形式(封装)数据。

  • 抽象

  • 三大特性:封装、继承、多态

  • 从认识论角度考虑:先有对象后有类。对象是具体的事物,类是对对象的抽象。

  • 从代码运行角度考虑:先有类后有对象。类是对象的模板

2. 方法回顾与加深

2.1 方法的定义

  • 修饰符

  • 返回类型

  • break 和 return 的区别

    • break : 跳出 switch;结束循环

    • return : 结束方法,返回一个结果!

  • 方法名

  • 参数列表 : (参数类型,参数名) ; double... numbers(可变长参数)

  • 异常抛出

2.2 方法的调用

  • 静态方法(有static修饰符) : 是和类一起加载的,即在 类存在的时候就存在

  • 非静态方法 : 只有在 类实例化之后才存在; 调用方法:new 方法所在的类().方法()

  • 形参和实参

 public class Demo03 {
     public static void main(String[] args) {
         // 实际参数和形式参数的类型要一一对应
         int add = new Demo03().add(2, 3);   // new 当前这个类().方法()
         System.out.println(add);
     }
     public int add(int a,int b){
         return a + b;
     }
 }
  • 值传递和引用传递

 //  值传递
 public class Demo04 {
     public static void main(String[] args) {
         int a =1;
         System.out.println(a);  // 1
 ​
         new Demo04().change(a);
         System.out.println(a);  // 1
     }
     public void change(int a){
         a = 10;
     }
 }
// 引用传递 :一般传递一个对象,但本质还是值传递
 public class Demo05 {
     public static void main(String[] args) {
         Person person = new Person();
         System.out.println(person.name); // null
 ​
         new  Demo05().change(person);
         System.out.println(person.name); // Lucky Y
 ​
     }
     public void change(Person person){
   // person 是一个对象:指向的------->Person person = new Person(),这是个具体的人,可改变属性
         person.name = "Lucky Y" ;
 ​
     }
 }
 ​
 // 定义了一个 Person 类,有一个属性:name
 class Person{
     String name;    // null
 }
  • this关键字

3. 对象的创建分析

3.1 类与对象的关系

  • 类 是一种抽象的数据类型,它是对某一事物整体描述/定义,但并不能代表某一个具体的事物。

  • 对象 是抽象概念的具体实例

3.2 创建与初始化对象

  • 使用new关键字创建对象

    • 使用new关键字创建的时候,除了分配内存空间外,还会 给创建好的对象进行默认的初始化 以及 对类中构造器的调用。

     package com.yang.OOP.demo02;
     //  学生类
     public class Student {
         // 属性:字段
         String name;
         int age;
     ​
         // 方法
         public void study(){
             System.out.println(this.name+"在学习");
         }
     }
    package com.yang.OOP.demo02;
     ​
     //  一个项目应该只存在一个 main方法
     public class Application {
     ​
         public static void main(String[] args) {
             // 类:是抽象的,需要实例化
             // 类实例化后会返回一个自己的对象!
             // student对象 就是一个 Student类 的具体实例
             Student student = new Student();
             student.name = "Lucky";
             student.age = 18;
             System.out.println(student.name);   // Lucky
             System.out.println(student.age);    // 18
         }
     }
    • 类中的构造器也称为 构造方法,是在进行创建对象的时候必须要调用的。

      • 构造器特点:

        1. 方法名必须和类的名字相同

        2. 必须没有返回类型,也不能写void

      • 构造器作用:

        1. new 本质在调用构造方法

        2. 初始化对象的值

      • 注意点:

        1. 定义有参构造后,若想使用无参构造,则必须 显示定义一个无参的构造

        2. this.当前类的 = 参数传进来的值

//  Person 类
 public class Person {
     // 一个类 即使什么都不写,它也会存在一个方法
     String name;
     int age;
 ​
     // 显示的定义构造器
     // 构造器的作用:1.实例化初始值 ;2.使用 new关键字,本质是调用构造器
     public Person(){
     }
 ​
     // 有参构造: 创建了有参构造器后,系统自带的 默认无参构造器 就会被覆盖掉
     public Person(String name,int age){
         this.name = name;
         this.age = age;
     }
 }
 ​
 /*
 public static void main(String[] args) {
         // 类:是抽象的,需要实例化
         // 类实例化后会返回一个自己的对象!
         // person对象 就是一个 Person类 的具体实例
         Person person = new Person("Lucky",18);
 ​
         System.out.println(person.name);
     }
  */

4. 简单小结类与对象

  1. 类与对象:类是一个模板(抽象的) ,对象是一个实例

  2. 方法:方法的定义、调用!

  3. 对象的引用

    • 引用类型:基本类型(8个)

    • 对象是通过 引用 来操作的:栈——————》堆(地址)

  4. 对象的属性:字段 Field( 成员变量)

    • 默认初始化:

      • 数字:0 0.0

      • char: u0000

      • 引用类型: null

      • boolean: false

    • 修饰符 属性类型 属性名 = 属性值

  5. 对象的创建和使用

    • 必须使用new关键字创造对像,创建对象需要构造器 Peraon lucky = new Person()

    • 对象的属性 lucky.name

    • 对象的方法 lucky.sleep()

  6. 类:

    • 静态的属性 属性

    • 动态的行为 方法

5. 面向对象三大特性(封装、继承、多态)

5.1 封装

  • 属性私有 get/set

  • 该露的露,该藏的藏

    • 程序设计要追求 “高内聚,低耦合”

    • 高内聚 即类的内部数据操作细节自己完成,不允许外部干涉;

    • 低耦合 即仅暴露少量的方法给外部使用。

  • 封装(数据的隐藏)

    • 通常 应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

  • 封装的意义:

    1. 提升程序的安全性,保护数据

    2. 隐藏代码的实现细节

    3. 统一接口,实现规范

    4. 提高系统的可维护性

package com.yang.OOP.demo04;
 ​
 public class Student {
     // 属性 私有
     private 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;
     }
 ​
     public int getId() {
         return id;
     }
 ​
     public void setId(int id) {
         this.id = id;
     }
 ​
     public char getSex() {
         return sex;
     }
 ​
     public void setSex(char sex) {
         this.sex = sex;
     }
 ​
     public int getAge() {
         return age;
     }
 ​
     public void setAge(int age) {
         if(age >120 || age < 0){
             System.out.println("年龄不合法!");
 ​
         }else{
             this.age = age;
         }
 ​
     }
 }
 /*
 package com.yang.OOP.demo02;
 ​
 import com.yang.OOP.demo04.Student;
 ​
 //  一个项目应该只存在一个 main方法
 public class Application {
 ​
     public static void main(String[] args) {
         Student s1 = new Student();
 ​
         s1.setName("Lucky");
 ​
         System.out.println(s1.getName());
 ​
         s1.setAge(70);
         System.out.println(s1.getAge());
 ​
     }
 }
 */

5.2 继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

  • extends 即 扩展。子类(派生类) 是 父类(基类) 的扩展

  • Java 中类只有单继承,没有多继承!

  • 修饰符优先级:public ----------> protected -----------> default ------------> private

 // Person 类:父类
 // Java中所有类都默认直接或间接继承 Object
 public class Person /*extends Object*/ {
     protected int money ;
 ​
     public void say(){
         System.out.println("子类继承父类,拥有父类的全部方法");
     }
     public int getMoney(){
         return money;
     }
 ​
     public void setMoney(int money) {
         this.money = money;
     }
 }
 =================================================================================
 // Student is Person:派生类  子类
 // 子类继承父类,拥有父类的全部方法
 public class Student extends Person{
     
 }
 ​
 ===============================================================================
 /*
 public static void main(String[] args) {
         Student student = new Student();
         student.say();
         student.setMoney(10_0000_0000);
         System.out.println(student.getMoney());
     }
     
 */
  • 继承是类和类之间的一种关系。除此之外类和类之间的关系还有依赖、组合、聚合等。

  • 在Java中所有类都默认直接或间接继承 object 类

  • super 注意点:

    1. super 调用父类的构造方法,必须在构造方法的第一个

    2. super 必须 只能出现在子类的方法或构造方法中

    3. super 和 this 不能同时调用构造方法

  • super & this:

    1. 代表对象不同

      • this : 代表本身调用者的 这个对象

      • super: 代表父类对象的引用

    2. 前提:

      • this : 在没有继承时也可以使用

      • super: 只能在继承条件下才可以使用

    3. 调用构造方法:

      • this() : 调用本类的构造

      • super() : 调用父类的构造

  • 没有 static 时,b调用的是对象的方法,而 b 是用 A 类 new 的;

  • 有 static 时,b 调用了B类的方法,因为 b 是用 B定义的。

  • 静态方法是类的方法,非静态方法是对象的方法 b 是 A new出来的对象因此非静态方法时调用了 A 的方法

  • 即静态属于类,非静态属于对象

//重写都是方法的重写,和属性无关
 public class B {
     public void test() {
         System.out.println("B=>test()");
     }
 }
 ​
 ===============================================================================
 // 继承
 public class A  extends B{
 ​
     @Override   //重写
     public void test() {
         System.out.println("A=>test()");
 ​
     }
 ​
    
 ==================================================================================
 ​
 /*    public static void main(String[] args) {
         // 方法的调用只和左边,定义的数据类型有关
         A a = new A();          //A=>test()
         a.test();
 ​
         // 静态方法时:父类的引用指向了子类  B=>test()
         B b = new A();  //非静态方法时:子类重写了父类的方法  A=>test()
         b.test();
     }
 */
  • 方法重写

    • 在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写(Override)。

      1. 方法名 和 参数列表 必须相同。

      2. 修饰符范围可以扩大,但不能缩小:public ---> protected ---> default ---> private

      3. 重写可能会抛出异常:重写范围可以被缩小,但不能被扩大

    • 为什么需要重写:

      1. 父类的功能,子类不一定需要,或者不一定满足!

5.3 多态

  • 动态编译 ,类型:可扩展。即同一方法可根据发送对象的不同而采用多种不同的行为方式

  • 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(一般指父类、有关系的类)

  • 多态存在的条件:有继承关系 、 子类重写父类方法、 父类引用指向子类对象 Father f1 = new Son()

    • 不能被重写的方法:

      1. static 方法,属于类不属于实例

      2. final方法 常量

      3. private方法

  • 注意:多态是方法的多态,属性没有多态性

// 父类
 public class Person {
     public void run(){
         System.out.println("run");
     }
 }
 // 子类
 public class Student extends Person {
     @Override   // 子类重写了父类的方法
     public void run() {
 ​
         System.out.println("son");
     }
     public void eat(){
         System.out.println("eat");
     }
 }
 import com.yang.OOP.demo06.Person;
 import com.yang.OOP.demo06.Student;
 ​
 public class Application {
 ​
     public static void main(String[] args) {
         // 一个对象的实际类型是确定的
         // 可以指向的引用类型就不确定了,父类的引用指向子类
 ​
         // Student  能调用的方法都是自己的或者继承父类的!
         Student s1 = new Student();
         //Person 父类型,可指向子类,但不能调用子类独有的方法
         Person s2 = new Student();
         Object s3 = new Student();
 ​
         // 对象能执行哪些方法主要看对象左边的类型,和右边关系不大
         
         s2.run();   //子类重写了父类的方法,执行子类的方法    son
         s1.run();   // son
 ​
         s1.eat();   //子类独有的方法
     }
 }

5.4 instanceof 和 类型转换

  • instanceof用法:对象 instanceof。用来判断左边是否是右边的实例或者后代

public static void main(String[] args) {
         //Object->String
         //Object->Person->Teacher
         //Object->Person->Student
         Object s1 = new Student();
         System.out.println(s1 instanceof Student); // true
         System.out.println(s1 instanceof Object);
         System.out.println(s1 instanceof Person);
         System.out.println(s1 instanceof Teacher);  //false
         System.out.println(s1 instanceof String);
     }
  • 类型之间的转换:高(父类) 转 低(子类)需要 强制转换,低(子类) 转 高(父类) 直接转换,但子类转换为父类可能会丢失自己本来的一些方法。可以方便方法的调用,减少代码重复!

public static void main(String[] args) {
         // 类型转换:父      子
 ​
         // 高            低
         Person s1 = new Student();
 ​
         // (Student) s1:将对象s1转换为Student类型,此时就可调用Student类型的方法了!
         Student s11 = (Student) s1;
         s11.eat();
         // 子类转换为父类,可能丢失自己本来的一些方法
         Person person = s11;    // 父类引用指向子类的对象
     }

6. 抽象类和接口

6.1 抽象类

如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。

因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。

使用abstract修饰的类就是抽象类。我们无法实例化一个抽象类:

 Person p = new Person(); // 编译错误
  • 抽象类的所有方法 必须要由继承了它的子类来实现

  • 作用:抽象类本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错。因此,抽象方法实际上相当于定义了“规范”。

  • 特点: 1. 不能 new 这个抽象类,只能靠子类去实现约束它 2. 抽象类里面可以写普通方法, 3. 抽象方法必须在抽象类中

6.2 接口

  • 普通类:只有具体的实现

  • 抽象类:具体实现和规范(抽象方法)都有

  • 接口:只有规范!自己无法写方法。专业的约束 约束与实现分离

接口的本质是契约,声明接口的关键字是interface它就像法律一样,制定好后大家都要遵守。

接口是OOP的精髓,是对 对象的抽象

 接口作用总结:
     1. Java 的接口是一个约束
     2. 它可以定义一些方法,让不同的人去实现
     3. 接口中的方法默认都是 public abstract
     4. 接口里面定义的属性 默认都是常量 public static final
     5. 接口不能直接被实例化,因为接口中没有构造方法
     6. implements可以实现多个interface
     7. 但是实现接口必须要重写里面的方法

7. 内部类

  • 内部类就是在一个类的内部再定义一个类。如:A 类中定义了一个B类,则 B类相对于A类来说就称为 内部类,A类 相对于 B 类来说就是外部类。

 public static void main(String[] args) {
     
         Outer outer = new Outer();
 ​
         // 通过外部类来实例化内部类
         Outer.Inner inner = outer.new Inner();
     
         inner.in();
         inner.getID();
     }
 ​
 ​
 public class Outer {
 ​
     private int id = 10;
     public void out(){
         System.out.println("这是外部类的方法");
     }
 ​
     public class Inner{
         public void in(){
             System.out.println("这是内部类的方法");
         }
         // 获得外部类的私有属性
         public void getID(){
             System.out.println(id);
         }
     }
 }
  • 要实例化一个Inner,我们必须首先创建一个Outer的实例,然后,调用Outer实例的new来创建Inner实例:Outer.Inner inner = outer.new Inner();

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值