面向对象编程(OOP)

1、初识面向对象

JAVA的核心思想就是OOP。

1.1、面向过程和面向对象:

面向过程思想:(线性思维)分析第一步、第二步…适合处理简单的事情。

面向对象思想:物以类聚,分类的思维,先考虑怎么分类,对每个分类进行单独思考,对分类的细节做面向过程的考虑。适合处理复杂的问题,多人协作的问题。

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

面向过程是具体的,面向对象是抽象的。三大特性:封装、继承、多态。

2、方法回顾和加深

2.1方法的定义

2.1.1&2.1.2 修饰符 & 返回类型

/*
* 修饰符 返回值类型 方法名字(...){
*  方法体
*  return 返回值
*  }*/
public String GOT7(){
    return "I GOT 7";
}
public void IGOT7(){
    return;
}
public int max(int a,int b){
    return a>b? a:b;
}

2.1.3 break和return的区别

break:跳出switch,结束循环。

return:代表方法的结束,返回一个方法,返回值可以是空也可以是返回返回值类型值.

2.1.4方法名

注意规范.见名知意.

2.1.5参数列表

(参数类型,参数名)...可变长参数

2.1.6异常抛出

见下一节。

2.2方法的调用(递归)

2.2.1静态方法

static:静态方法,在另一个类中可以直接使用类名.方法名来调用。

注意:在一个类中,一个是static方法,一个不是,则static方法不可以调用非静态方法。因为static和类是一起加载的,而非静态方法是在类实例化之后才存在。

2.2.2非静态方法

无static:非静态方法,在一个类中通过实例化(创建一个对象):new 对象名().方法名()【对象类型 对象名 =new 对象值; 对象名.方法名()】来调用。

2.2.3形参和实参

形参是不存在的,实参是存在的,他们值类型必须一致。

2.2.4值传递和引用传递

JAVA是值传递:

public static void main(String[] args) {
  int a=1;
    System.out.println(a);
    change(a);
    System.out.println(a);
}
public static void change(int a){
    a=10;
}

输出结果:1 1

因为并没有返回值。

引用传递:传递一个对象(一个类中只能有一个public类,但是可以有多个class)

 public static void main(String[] args) {
     GOT7 leader= new GOT7();
     leader.name="段宜恩";
     System.out.println(leader.name);
     change(leader);
        System.out.println(leader.name);
    }
    public static void change(GOT7 leader){
        leader.name="林在范";
    }


}
    class GOT7{
        String name;
    }

输出结果:段宜恩 林在范

leader是一个对象,指向GOT7类

2.2.5 this关键字&&构造器

this是指向类的。例如this.name=name

//意思是this.name就是类的成员变量=方法中定义局部变量.

类(关键字是class)和对象的关系:

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

对象是抽象概念的具体实例。(leader对象)

对象的创建:

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

一个类中只有属性和方法。

public class GOT7 {
    String name;
    int age;
    public void  vocal(){
        System.out.println(this.name+"林在范和崔荣宰");
    }
}

public class Oop01 {
    public static void main(String[] args) {
       GOT7 cyj=new GOT7();
       cyj.name="崔荣宰";
       cyj.vocal();
    }
}

类中构造器也称为构造方法,是在创建对象时必须要调用的,必须和类的名字相同,必须没有返回类型,也没有void。每个类都有一个无参构造器。

构造器作用:①使用new关键字时必须有构造器(因为new本质时调用构造器)。②用来初始化值。

public class GOT7 {
    String name;
    int age;
    public void  leader(){
        System.out.println(this.name);
    }
    //无参构造器
    public GOT7(){
      this.name="林在范";
    }
    //有参构造器(一旦定义了有参构造,且是使用到了new,则无参构造器必须显式定义,否则new会报错:无法将类构造器应用到给定类型)
    public GOT7(String name){
        this.name=name;
    }
}

3、对象的创建分析

1、对象使用过引用来操作的。从栈到堆(地址)。

2、属性:字段filed 成员变量

3、默认初始化:数字:0 0.0

​ char:u0000

​ boolean:false

​ 引用:null

4、对象必须使用new关键字来创建。

4、面向对象三大特性

4.1、封装

程序要求:高内聚(类的内部数据操作细节自己完成不允许外部干涉)、低耦合(仅暴露少量的方法给外部使用)

封装:禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问。

属性私有:get/set

注意:写一个Student类,有姓名,性别等属性,如果属性是公有的,那么在别的类中可以通过new一个类对象来直接使用,即

Student Jackson=new Student();

Jackson.name="王嘉尔" ;

但是如果属性是私有(private)的,那么不可以直接对象.属性。而是要给Student类属性添加get/set方法,通过Jackson.getName()来对属性进行操作。

封装的意义:

提高程序的安全性,保护数据;

隐藏代码实现细节

统一接口

提高系统可维护性

为什么println可以输出多种类型的数据:因为方法重载.

同一个类中 两个方法 如果方法名一致,参数列表一致,那一定是同一个方法.

4.2、继承

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

extends是扩展的意思,子类是父类的扩展;

Java中类只有单继承,没有多继承;(一个儿子只有一个爸爸,但是一个爸爸可以有多个儿子)

接口可以多继承。

继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等;

继承关系的两个类,一个是子类(派生类),一个是父类(基类)。子类继承父类,使用关键字extennds来表示;子类继承父类拥有父类所有公共的方法。私有的东西是无法继承的。一般属性是私有的。

public class GOT7 {
    private String name;
    private int age;
    public void play(){
        System.out.println("GOT7 is playing");
    }
}
=================================
public class Rapper extends GOT7 {

}
=================================
public class Oop02 {
    public static void main(String[] args) {
        Rapper rappers= new Rapper();
        rappers.play();
    }
}

object类

在Java中,所有的类都默认直接或者间接继承object类。

之后会更详细的学习。

super&this

this是当前类,super是(调用)父类。

this没有继承也可以使用,super必须在有继承条件才能使用。

public class GOT7 {
    protected String name="JBMARKJACKSONPJRCRJBAMBAMKYG";
    private int age;
    public void play(){
        System.out.println("GOT7 is playing");
    }
}
=======================================
public class Rapper extends GOT7{
       private String name="MARKJACKSONBAMBAM";
       public void test(String name){
           System.out.println(name);
           System.out.println(this.name);
           System.out.println(super.name);
       }
}
=======================================
public class Oop02 {
    public static void main(String[] args) {
        Rapper rappers= new Rapper();
        rappers.test("GOT7的名字");
    }
}
=======================================
输出结果:
GOT7的名字
MARKJACKSONBAMBAM
JBMARKJACKSONPJRCRJBAMBAMKYG

注意:

子类继承父类,在new一个子类对象时候,子类构造器会先调用父类的无参构造器,而且构造器中有“super()”这一行是存在的,执行了的但是没有显示,如果写出来,必须写在子类的构造器的第一行。

this也必须是第一个参数,所以super和this不能同时调用构造方法。

父类没有无参构造的话,子类也无法写无参构造。所以一旦创建了有参构造器,那么最好把无参构造器也写上。

super只能出现在子类的构造方法或者方法中。

方法重写

重写都是方法的重写,和属性无关。

重写需要有继承关系,只能是子类重写父类的方法,且方法名和参数列表都是一样的,方法体不同。

静态方法和非静态方法是有区别的。重写只和非静态方法有关,与静态方法无关。

父类和子类的方法都是public的,修饰符可以扩大,但是不能缩小:public>protected>default>private

(抛出的异常,范围可以缩小,但是不能被放大。ClassNotFoundException<Exception)

例如:B是A的父类:当A和B中都是静态方法时:父类的引用 指向了子类(可以通过父类new一个子类):(方法的调用值和定义的数据类型有关(即等号左边的A,B)对象能执行哪些方法主要看对象左边的类型,和右边关系不大 【两个类型A、B都有该非静态方法时,执行子类,因为重写了】) 输出结果为:A和B各自的方法。

A a=new A();

B b=new A();

当A和B都是非静态方法时,输出结果为:都是A的方法。因为A重写了B的方法。

为什么需要重写?

子类不一定需要父类方法,或者不一定能被满足。

static属于类,不属于实例,不能被重写;

final是常量,不能被重写;

private是私有的,不能被重写;

4.3、多态

多态可以实现动态编译。

即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。

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

多态存在的条件:

有继承关系

子类重写父类方法

父类引用指向子类对象

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

instanceof

(类型转换)引用类型,判断一个对象是什么类型。判断是否存在两个类之间是否存在父子关系。

GOT7 got7=new Rapper();
Object rappers= new Rapper();
Object vocal=new Vocal();
System.out.println(rappers instanceof Rapper);//true
System.out.println(vocal instanceof Vocal);//true
System.out.println(got7 instanceof GOT7);//true
System.out.println(got7 instanceof Object);//true
System.out.println(vocal instanceof String);//false

//System.out.println(got7 instanceof  String); 编译报错 GOT7和String时同级别的。

类型转换:

基本类型转化:高转低强制

类:父类和子类之间的转化:父类时高 子类是低

//低转高  不需要强制转换
高             低
GOT7 got7=new Rapper();
//高转低   强制转换需要带括号
Rapper rapper=(Rapper)got7;

子类转换为父类,可能会丢失自己本有的一些方法。

Vocal vocal=new Vocal();
GOT7 got=vocal;

父类引用指向子类对象;

子类转换成父类,向上转型;

父类转换成子类,强制转换,会丢失方法

是为了减少重复的代码。

static小结

变量:static修饰的变量可以通过类名.属性名称来访问

方法:static修饰的方法在本类中可以使用(类名.)方法名直接被main方法访问,非静态方法需要new一个对象才能被使用。

静态方法可以调用静态方法,不能调用非静态方法。

静态代码块

{
    System.out.println("匿名代码块");
}
    static {
    System.out.println("静态代码块");
    }

    public GOT7() {
        System.out.println("构造器");
    }

    public static void main(String[] args) {
        GOT7 g=new GOT7();
        GOT7 got7=new GOT7();
    }
}
输出结果:
静态代码块
匿名代码块
构造器
匿名代码块
构造器

匿名代码块可以用来赋初值。

静态代码块只执行一次。

静态导入包:

import static java.lang.Math.random;

package javademo;
import static java.lang.Math.random;

public class Oop02 {
    public static void main(String[] args) {
        System.out.println(random());
    }
}

被final修饰的类不可以被继承。final之后断子绝孙

5、抽象类和接口

5.1抽象类(抽象的抽象)

abstract修饰符可以用来修饰方法,也可以用来修饰类。

public abstract class Action {
    public abstract void  dosth();
}

抽象类中可以没有抽象方法,但是有抽象方法的类就一定要声明为抽象类。(抽象方法必须在抽象类中)

抽象类,不能使用new关键字来创建对象,只能通过new子类来创建对象。他是用来让子类继承的。他就是一个约束。

抽象方法,只有方法的声明,没有方法的实现,(只有方法名字,没有方法体,没有{})它是用来让子类实现的。

子类继承抽象类,那么就必须要实现抽象类没有是实现的抽象方法,除非该子类也为抽象类。

抽象类不能被new,那是否存在构造器?存在,可以用来初始化一些字段。

抽象类存在的意义? 抽象共有属性,提高开发效率。

5.2接口

普通类(类关键字:class):只有具体实现。

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

接口(接口关键字是Interface):只有规范。自己无法写方法。约束和实现分离。面向接口编程。

接口就是规范,定义的是一组规则。如果你是……,那你就会……

接口的本质是契约。规定了需要遵守。

OO的精髓,是对对象的抽象,而接口最能体现这一点。

接口中的方法都是抽象的。public abstract

接口需要有实现类。实现(implements)了接口的类就需要重写接口中的方法。

接口中那个定义的都是常量。public static final

package javademo;

public interface UserService {
    int AGE=99;
    void  add();
    void  del();
}
==============================
package javademo;

public interface TimeService {
    void  add1();
    void  del1();
}
=============================
package javademo;

public class UserServiceImpl implements UserService,TimeService {
    @Override
    public void add() {

    }

    @Override
    public void del() {

    }

    @Override
    public void add1() {

    }

    @Override
    public void del1() {

    }
}

接口作用:

是一个约束,可以定义多种公共的抽象方法,可以实现多个接口,实现接口必须要重写方法。

6、内部类

内部类就是在一个类的内部定义一个类。

一个java类中可以有多个class类,但是只能有一个public class

并不推荐大量使用内部类。

6.1成员内部类

package javademo;
public class Oop02 {
   private  int id;
   public  void  out(){
       System.out.println("外部类");
   }
    class Inner{
       public void in(){
           System.out.println("内部类");
       }
   }

    public static void main(String[] args) {
       Oop02 out=new Oop02();
       out.out();
       Oop02.Inner inner= out.new Inner();
       inner.in();
    }
}

6.2静态内部类

package javademo;
public class Oop02 {
   private  int id;
   public  void  out(){
       System.out.println("外部类");
   }
    public static class Inner{
       public void in(){
           System.out.println("内部类");
       }
   }

    public static void main(String[] args) {
       Oop02 out=new Oop02();
       out.out();
       Inner inner=new Inner();
       inner.in();
    }
}

6.3局部内部类

在方法中的类

package javademo;
public class Oop02 {
   private  int id;
   public  void  out(){
       class Inner{
           public  void run() {
               System.out.println("局部内部类");
           }
       }
   }
}

6.4匿名内部类

匿名对象的使用,不用将实例保存在变量中

package javademo;
public class Oop02 {
   private  int id;

    public static void main(String[] args) {
        new A().eat();
    }

}
class A{
    public void eat(){
        System.out.println("1");
    }
}