Java面向对象

面向对象OOP

OOP的本质:以类的方式组织代码,以对象的方式组织(封装)数据

抽象

对象是具体的事物,类是对对象的抽象

先有类后有对象,类是对象的模板

 

方法

方法的调用

 1  //1、静态方法——直接调用
 2  public class Student {
 3      public static void speak(){
 4          System.out.println("ooooo");
 5      }
 6  }
 7  public class Demo01 {
 8      public static void main(String[] args) {
 9          //类名.方法名 即可调用
10          Student.speak();
11      }
12  }
13 14  //2、非静态方法——需要实例化这个类
15  public class Student {
16      public void speak(){
17          System.out.println("ooooo");
18      }
19  }
20  public class Demo01 {
21      public static void main(String[] args) {
22          //实例化这个类Student
23          //对象类型 对象名 = 对象值
24          Student student = new Student();
25          student.speak();
26      }
27  }

 

  • 静态方法和类一起加载,非静态方法在类实例化之后才存在,不能在静态方法中调用非静态方法

 

对象的创建分析

一个项目应该只存在一个main方法,通常在Application类中定义

类是抽象的,需要实例化,实例化后会返回一个自己的对象,通过new关键字可以创建不同的实例

  • new关键字创建对象

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

  • 构造器(类似C++的构造函数?)

    构造器也称为构造方法,必须和类的名字相同,必须没有返回类型(也不能写void)

    构造器的作用:①使用new关键字时本质上是在调用构造器;②用于初始化值

    一旦定义了有参构造,就必须对无参构造进行显式定义

    (idea中alt+insert快捷生成构造器constructor—>直接生成有参/select no生成无参)

 1  //定义的学生类
 2  public class Student {
 3      //属性:字段(静态)
 4      String name;
 5      int age;
 6      //方法(动态)
 7      public void study(){
 8          System.out.println(this.name+"studying");
 9      }
10      
11      //无参构造器
12      public Student() {
13      }
14      //有参构造器
15      public Student(String name, int age) {
16          this.name = name;
17          this.age = age;
18      }
19  }
20  ====================================================
21  public class Application {
22      public static void main(String[] args) {
23 24          //实例化默认对象(调用无参构造)
25          Student student01 = new Student();
26          //实例化对象的同时赋值(调用有参构造)
27          Student student02 = new Student("COLIN",23);
28          System.out.println(student02.name);
29          
30          student01.study();
31          
32      }
33  }

 


 
  • new对象

  • 相当于只是创建了一个引用变量,包含的值和方法存储在堆中,模板存储在方法区(方法区也属于堆)

  • 栈存放引用,堆存放具体对象

  • 静态方法区static和类一起加载,可以被所有的对象调用

面向对象的三大特性(难点)

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

(修饰符

  • public:类成员能被所有的类直接访问

  • protected

    1. 父类的protected方法/属性在同一个包内可见,且子类可见;

    2. 若子类与父类不在同一包中:

      那么在子类中,子类实例可以访问其从父类继承而来的protected方法,而不能访问父类实例本身的protected方法/属性。(自己的理解:父子不同包时,不能通过父类实例化后的对象来访问父类的protected方法/属性,相当于不能直接访问父类的protected对象,必须通过继承)

  • Default(无修饰符):类成员只能被同一个包中的类访问

  • private:类成员只能在修饰它的类中被访问,不可以被外部类访问,对外提供get/set方法(封装思想)

封装

“高内聚,低耦合”

  • 属性私有

  • 通过get/set访问和修改

 1  public class Student {
 2      //属性私有
 3      private String name;
 4      private int id;
 5      private int age;
 6  7      //提供一些可以操作这些属性的方法
 8      //即pubilc的get、set方法
 9      //get
10      public String getName(){
11          return this.name;
12      }
13      //set
14      public void setName(String name){
15          this.name = name;
16      }
17      //可以通过内部的封装让程序更安全
18      //alt+insert 自动生成getter/setter
19  }
20 21  public class Application {
22      public static void main(String[] args) {
23 24          Student student = new Student();
25          student.setName("colin");
26          System.out.println(student.getName());
27      }
28  }
  • 封装的好处

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

    2. 隐藏代码的实现细节

    3. 统一接口

    4. 增加系统的可维护性

继承

继承的本质是对某一批类的抽象,是类之间的一种关系(类之间还有依赖、组合、聚合等关系)

子类继承父类:

  • 使用关键字extends + 继承的类来表示继承

  • 子类拥有父类的全部public属性和方法(私有private不能继承,protected在不同包时必须通过继承实例化才能访问)

  • Java中所有的类都默认继承object类

子类只能有一个父类

final修饰的类不能被继承

 1  //Ctrl+H打开继承树
 2  //默认、this、super
 3  public class Father {
 4      protected String name = "xxx";
 5      
 6      public void print(){
 7          System.out.println("Father");
 8      }
 9  }
10  ==============================================
11  //通过extends继承
12  public class Son extends Father{
13 14      private String name = "yyy";
15 16      public void test(String name){
17          //默认调用本方法属性
18          System.out.println(name);       //zzz
19          //this调用本类属性
20          System.out.println(this.name);  //yyy
21          //通过super调用父类的属性
22          System.out.println(super.name); //xxx
23      }
24      
25      public void print(){
26          System.out.println("Student");
27      }
28 29      public void test1(){
30          //默认调用本类方法
31          print();            //Student
32          //this调用本类方法
33          this.print();       //Student
34          //super调用父类方法
35          super.print();      //Father
36      }
37  }
38  ===============================================
39  public class Application {
40      public static void main(String[] args) {
41          Son son = new Son();
42          son.test("zzz");
43          son.test1();
44      }
45  }

 

子类会默认调用父类的无参构造,调用父类的构造器,必须要在子类的第一行

  • super调用父类方法的注意点:

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

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

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

  • super和this的区别

     thissuper
    代表的对象 调用对象本身 调用对象的父类
    前提 没有继承也可以使用 只能在继承条件下使用
    构造方法 本类的构造 父类的构造

(方法重写

重写需要有继承关系,只适用于非静态子类可以重写父类的方法

  1. 方法名必须相同,方法体可以不同

  2. 参数列表必须相同

  3. 修饰符范围可以扩大不能缩小:public>protected>Defalt>private

  4. 抛出的异常范围可以被缩小,但不能扩大

为什么需要重写:

  1. 父类的功能子类不需要,或不满足

idea快捷键:在子类中使用Alt + Insert—>overwrite

多态(还没有完全理解!)

多态:同一个方法根据发送对象不同而采取不同的行为方式

  • 父类的引用指向子类的对象

  • 对象可以执行的方法取决于对象名左边的对象类型(即对象的引用类型)

    Person student = new Student(); (对象类型 对象名 = 对象值);

 

父类的引用可以指向子类,但父类不能调用子类的方法对象可执行的方法取决于对象左边的类型

 1  public class Person {       //父类
 2      public void run(){
 3      }
 4  }
 5  public class Student extends Person{        //子类
 6      public void run(){        
 7      }
 8      public void eat(){        
 9      }
10  }
11 12  public class Application {
13      public static void main(String[] args) {
14          //可以指向的引用类型不确定,父类的引用可以指向子类
15          //对象可执行的方法取决于对象左边的类型
16          Student s1 = new Student();
17          //父类的引用可以指向子类对象,但父类不能调用子类的方法
18          Person s2 = new Student();
19          Object s3 = new Student();
20          //多态实例:
21          s1.run();
22          s2.run();//这里子类重写了父类的方法,执行子类的方法
23          s1.eat();
24          s2.eat();//Person中没有eat方法,所以不能执行
25                   //需要进行强制类型转换:((Student) s2).eat();
26      }
27  }

 

多态的注意事项:

  1. 多态是方法的多态,属性没有多态

  2. 父类和子类必须有联系才能转换(类型转换异常ClassCastException)

  3. 多态存在的条件:继承关系,方法重写,父类引用指向子类对象

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

多态的意义:??

(instanceof

X instanceof Y 判断两者类型是否有父子关系,如果不在同一分支上(没有父子关系或间接父子关系)会报错

X和Y有父子关系且X实际指向的类型是Y的子类型则返回true,否则返回false

 1  public class Application {
 2      public static void main(String[] args) {
 3          
 4          //Object > String
 5          //Object > Person > Teacher
 6          //Object > Person > Student
 7          
 8          Object object = new Student(); 
 9          //object实际指向的类型为Student           
10          System.out.println(object instanceof Student);  //true
11          System.out.println(object instanceof Person);   //true
12          System.out.println(object instanceof Object);   //true
13          System.out.println(object instanceof Teacher);  //false
14          System.out.println(object instanceof String);   //false
15          
16          Person person = new Student(); 
17          System.out.println(person instanceof Student);  //true
18          System.out.println(person instanceof Person);   //true
19          System.out.println(person instanceof Object);   //true
20          System.out.println(person instanceof Teacher);  //false
21          System.out.println(person instanceof String);   //编译报错
22 23          Student student = new Student(); 
24          System.out.println(student instanceof Student);  //true
25          System.out.println(student instanceof Person);   //true
26          System.out.println(student instanceof Object);   //true
27          System.out.println(student instanceof Teacher);  //编译报错
28          System.out.println(student instanceof String);   //编译报错        
29      }
30  }

 

(类型转换

子类转换为父类,向上转型,自动转换,可能丢失自己本来的一些方法

父类转换为子类,向下转型,强制转换

意义:减少重复代码

(static关键字

  1. 静态/非静态变量

    • 静态变量可以通过 类名.变量名 访问,整个包中同名静态变量只有一个,被共享,任意位置可以修改

1  public class Father {
2      public static int age = 100;
3  }
4  ====================================
5  public class Application {
6      public static void main(String[] args) {
7          System.out.println(Father.age);     //输出100
8      }
9  }

 

  1. 静态/非静态方法

    • 静态方法可以直接通过类名调用

    • 非静态方法可以直接访问类中静态的方法

    • 未加载类之前不能使用非静态的方法

  2. 匿名代码块/静态代码块

     1  public class Person {
     2      //2 用于赋初值
     3      {
     4          System.out.println("匿名代码块");
     5      }
     6      //1 最先执行,且只执行一次
     7      {
     8          System.out.println("静态代码块");
     9      }
    10      //3 执行构造方法
    11      public Person(){
    12          System.out.println("构造方法");
    13      }
    14 15      public static void main(String[] args) {
    16          Person person = new Person();
    17      }
    18  }

     

  3. 静态导入包

    1  import static java.lang.Math.random;
    2 3  public class Person {
    4      public static void main(String[] args) {
    5          System.out.println(random());
    6          //静态导入不需要Math. + random()就可以执行
    7      }
    8  }

     

     

 

抽象类和接口

抽象类

 1  //抽象类
 2  //extends是单继承的 (接口可以多继承)
 3  public abstract class Action {
 4      //抽象方法,只有方法名,没有方法的实现
 5      public abstract void dosomething();
 6  }
 7  //继承了抽象类的子类,必须要重写方法,除非子类也是抽象类
 8  public class A  extends Action{
 9      @Override
10      public void dosomething() {
11      }
12  }

 

  • 抽象类的注意事项:

    • 不能(实例化)new抽象类,只能通过子类去实现

    • 抽象类中可以写普通方法,抽象方法必须写在抽象类中

    • 抽象类构造器:抽象类中可以有构造器,因为抽象类中可以有普通变量,而接口不能有构造器

    • 抽象类存在的意义:约束、提高开发效率

接口

  • 普通类:只有具体实现

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

  • 接口:只有规范(抽象方法)

接口就是规范,定义的是一组规则,约束和实现分离:面向接口编程

接口的本质是契约、约束

  • 接口是一种约束,只能定义方法名

  • 子类实现接口,必须重写其中的方法

  • 只有一个方法的接口叫做函数式接口

 1  //定义接口的关键字:interface
 2  public interface UserService {
 3      //接口中的所有定义的方法其实都是抽象的,方法默认是public abstract
 4      //接口中定义的属性默认都是常量 public static final (通常不在接口中定义常量)
 5      int age = 99;
 6      void run();
 7  }
 8  public interface TimeService {
 9      void timer();
10  }
11  =========================================================================
12  //接口的实现类一般使用Impl作结尾
13  //类实现接口:implements + 接口
14  //实现了接口的类必须要重写接口中的方法
15  //利用接口就可以实现多继承!
16  public class UserServiceImpl implements UserService,TimeService{
17      @Override
18      public void run() {
19      }
20      @Override
21      public void timer() {
22      }
23 24      public static void main(String[] args) {
25          System.out.println(UserService.age);
26      }
27  }

 

  • 接口的作用

    1. 约束

    2. 定义了一些方法,让不同的人实现

    3. 接口中定义的方法默认都是抽象的,属性默认都是常量

    4. 接口不能被实例化(因为接口中没有构造方法)

    5. implements可以实现多个接口

    6. 必须要重写接口中的方法

 

内部类

内部类:在一个类的内部再定义一个类,分为:①成员内部类 ②静态内部类 ③局部内部类 ④匿名内部类

 1  public class Outer {
 2  3      private int id = 101;
 4      public void out(){
 5          System.out.println("这是外部类的方法");
 6          //局部内部类:方法中的内部类
 7          class B{}
 8      }
 9 10      //内部类可以操作外部类的私有属性/方法
11      //但静态的内部类不能访问外部类(静态先实例化)
12 13      //成员内部类:
14      public class Inner{
15      //静态内部类:
16      //public static class Inner{
17          public void in(){
18              System.out.println("这是内部类的方法");
19          }
20          public void getID(){
21              System.out.println(id);
22          }
23      }
24  }
25 26  //一个java类中可以有多个class类,但只能有一个public class类
27  class A{
28  }
29  =======================================================
30  public class Application {
31      public static void main(String[] args) {
32 33          Outer outer = new Outer();
34          //通过外部类来实例化内部类
35          Outer.Inner inner = outer.new Inner();
36          inner.getID();
37 38          //匿名内部类:不用将实例保存到变量中
39          new Outer().out();
40 41      }
42  }

 

 

posted @ 2021-03-07 00:18  Colin13  阅读(34)  评论(0)    收藏  举报