20200310学习JAVA笔记:面向对象编程

面向对象编程

(OOP,Object-Oriented Programming)

初识面向对象

20200310学习JAVA笔记:面向对象编程_第1张图片

什么是面向对象

面向对象是搭建框架,面向过程是实现流程。

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

抽象:将类似的、同类的事物抽取出来。

三大特征:

  • 封装:将数据封装起来,对外提供一个接口来使用。
  • 继承:子类继承父类,得到父类的所有属性,被继承的类叫父类。
  • 多态:

类和对象:对象是具体的事物,类是对象的模板。例如“猫”是一个类,具体的一只猫就是一个对象,这只猫的颜色、大小、品种就是这个对象的属性。从代码运行的角度看是先有类后有对象。

方法回顾与加深

方法的定义

  • 修饰符

  • 返回类型

  • 方法名:见名知意,驼峰命名法

  • 参数列表:参数类型,参数名。

  • break和return的区别:break结束switch、跳出循环;return结束方法,返回一个结果。

  • 异常跳出

    package oop;
    
    import java.io.IOException;
    
    public class Demo01 {
        public static void main(String[] args) {
    
        }
        /*修饰符   返回值类型   方法名(参数)
        {
        //方法体
        return  返回值;
        }
         */
        public String sayHello()
        {
            return "Hello,world!";
        }
        public int max(int a,int b)//a,b是形参,实参和形参要一一对应
        {
            return a>b?a:b;
        }
        //异常:数组下标越界:Arraysindexoutofbounds
        public void readFile(String file) throws IOException{}//抛出异常
    }
    
    

方法的调用

  • 静态方法与非静态方法

    package oop;
    
    public class Demo02 {
        public static void main(String[] args) {
    
        }
        //静态方法 static
        //非静态方法 没有static
       public static void a(){
    
       }//静态方法、类方法和类一起加载
        public void b(){
        a();//静态方法在同一类下可以直接调用,也可以通过类直接调用
            // Demo02.a();    
        }//b是非静态方法、对象方法,要类实例化之后才存在
    }
    
    
    package charactor;
     
    public class Hero {
        public String name;
        protected float hp;
     
        //实例方法,对象方法,非静态方法
        //必须有对象才能够调用
        public void die(){
            hp = 0;
        }
         
        //类方法,静态方法
        //通过类就可以直接调用
        public static void battleWin(){
            System.out.println("battle win");
        }
         
        public static void main(String[] args) {
               Hero garen =  new Hero();
               garen.name = "盖伦";
               //必须有一个对象才能调用
               garen.die();
                
               Hero teemo =  new Hero();
               teemo.name = "提莫";
                
               //无需对象,直接通过类调用
               Hero.battleWin();
             
        }
    }
    
  • 形参和实参:形参就是方法中的形式上的参数,实参是调用方法时传递给方法的实际参数,形参和实参要保证类型的一致。

  • 值传递:
    在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。

    如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值(拥有数据),并且是在不同的栈区,因此形参的操作,不影响原始内容。

    package oop;
    //值传递
    public class Demo04 {
        public static void main(String[] args) {
            int a=1;
            System.out.println("a = " + a);
            Demo04.change(a);
            //输出a=1;值传递传递的是真实内容的一个副本,对副本的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。
            a=Demo04.change(a);//这里是将返回值赋值给a,a得到了新的值。
            System.out.println("a = " + a);//输出a=10;
        }
        public static int change(int a){
            a=10;
            return a;
        }
    }
    
    
  • 引用传递:

    实际上也是值传递。对象是指向数据的,对象并不拥有数据,所以指向不变的时候,数据是可以被改变的。对引用类型的数据进行操作,分两种情况,一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。

    package oop;
    //引用传递,本质还是值传递
    public class Demo05 {
        static class Person{
            String name;
            public void changeName(Person person){
                person.name="辛幼安";
            }
        }
        public static void main(String[] args) {
            Person person=new Person();
            person.name="辛弃疾";
            person.changeName(person);//对象方法,通过对象来调用
            System.out.println(person.name);//输出辛幼安
        }
    
    }
    
    
    package oop;
    //引用传递,本质还是值传递
    public class Demo05 {
        static class Person{
            String name;
            public void changeName(String name){
                name="辛幼安";
            }
        }
        public static void main(String[] args) {
            Person person=new Person();
            person.name="辛弃疾";
            person.changeName(person.name);//对象方法,通过对象来调用
            System.out.println(person.name);//输出辛弃疾,因为person是对象,person.name是一个具体值
        }
    
    }
    
    

    因此可见:在Java中所有的参数传递,不管基本类型还是引用类型,都是值传递,或者说是副本传递。

  • this关键字

对象的创建分析

类与对象的创建

20200310学习JAVA笔记:面向对象编程_第2张图片

package oop;
//学生类,任何一个类都只包含属性和方法
public class Student {
    //属性
    String name;
    int age;
    //方法
    public void study(){
        System.out.println(this.name+"在学习!");
    }

    public static void main(String[] args) {
        //类是抽象的,需要实例化。对象就是Student类的具体实例
        Student student1=new Student();
        student1.name="小明";//如不赋值,则默认初始化为null
        student1.age=10;//默认初始化为0;

        Student student2=new Student();
        student2.name="小红";
        student2.age=9;
    }
}

构造器/构造函数详解

构造器的特点与作用:

  1. 和类名相同,没有返回值。
  2. new的本质在调用构造方法,用来初始化对象的值
  3. 使用有参构造,则无参构造就默认没了。
  4. 在定义有参的构造器后,如果想使用无参构造,要显示一个定义的无承诺构造。
  5. 重写了一个有参构造,一般加上一个无参构造。
    String name;
    int age;
    //一个类即使什么也不写,也会存在一个方法,会有一个默认的空构造器;
    //构造器没有返回值,名字与类名相同
    //public Person(){}


    //实例化初始值
    //1.使用new关键字必须要有构造器。
    //2.用来初始化值
    public Person(){
        this.name="辛弃疾";
    }
    //有参构造一旦被定义,有参构造就必须被显示定义
    public Person(String name){
        this.name=name;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        Person person=new Person("辛弃疾");
        Person person1=new Person("陆游",55);
    }

    //生成构造方法的快捷键:alt+Ins(Shift)

创建对象的内存分析

20200310学习JAVA笔记:面向对象编程_第3张图片

简单小结类与对象

  1. 类是一个模板,抽象;对象是一个具体的实例。

  2. 方法:定义和调用;

  3. 对应的引用:引用类型、8个基本类型。对象是通过引用来操作的。栈—>堆

  4. 属性:成员变量

    默认初始化:

    • 引用:null;

    • 数字:0;

    • char:u000;

    • boolean:false;

      赋值: 修饰符 属性名=属性值

  5. 对象的创建和使用:必须使用new关键字创造对象,通过构造器。

    对象的方法、属性都是通过点(.)操作符来调用。

  6. 类:静态的属性;动态的行为——方法。

面向对象的三大特性

封装(private

20200310学习JAVA笔记:面向对象编程_第4张图片

package oop;

import java.util.Arrays;

//学生类,任何一个类都只包含属性和方法
public class Student {
    //姓名,学号,性别,年龄,学习();
    //封装主要是对于属性,属性私有;
    private String name;
    private int id;
    private char sex;
    private int age;
    //提供一些可以操作这些属性的方法。
    //set 给这个数据设置值
    public void setName(String name){
        this.name=name;
    }
    //get 获得这个数据
    public String getName(){
        return this.name;
    }
    //alt+insert(Shift)自动生成get,set方法;

    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;
        }
    }

    public static void main(String[] args) {
        Student student1=new Student();
        student1.setName("小明");
        student1.name=student1.getName();
        System.out.println(student1.name);
    }
}

  1. 提高程序的安全性。
  2. 隐藏代码的实现细节。
  3. 统一接口。
  4. 增加系统的可维护性。

继承

20200310学习JAVA笔记:面向对象编程_第5张图片

1. Object类

pulic class Student extends Person{}
package oop;

public class Person {
  //属性一般是私有的,可以通过get,set方法来接入
   private int money=10_0000_0000;

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    public void say(){
        System.out.println("说了一句话!");
    }
}
/*------------------------------------------*/

package oop;

import java.util.Arrays;

//子类继承父类,会继承父类的所有的方法
public class Student extends Person{
    public static void main(String[] args) {
        Student student1=new Student();
        int a=student1.getMoney();
        student1.say();
    }
}
//在类里面使用Ctrl+H,打开继承关系的列表

所有的类都默认继承Object类

public class Person extends Object{}
//就等于
public class Person {}

2. super

20200310学习JAVA笔记:面向对象编程_第6张图片

  • super用于调用父类的属性和方法。
  • super调用父类的构造方法,必须在构造方法的第一个。
  • super必须只能出现在子类的方法或者构造方法中。
  • super和this不能同时调用构造方法。

VS this:

  • 代表的对象不同。this:本身调用的这个对象;super:代表父类对象的应用。
  • 前提不同。this:没有继承也可以使用;super:只能在继承条件才可以使用。
  • 构造方法。this()是本类的方法;super()是父类的方法。

3. 方法重写

  • 重写是方法的重写,和属性无关,需要有继承方法,是子类重写父类的方法。
  • 方法名和参数列表必须相同
  • 重写是对非静态方法,静态方法没有重写。
  • 修饰符是private的不能重写。修饰符范围可以扩大不能缩小。public>protected>default>private
  • 抛出的异常:范围可以缩小不能扩大。
  • 子类的方法必须和父类一致,但方法体不同。

为什么需要重写?

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

    重写快捷键:alt+Ins(Shift)–>override

package oop;
//将A类作为父类
public class A {
    protected void test(){
        System.out.println("test=>A");
    }
}

package oop;
//B作为子类
public class B extends A {
    @Override
    //非静态方法
    protected void test() {
        System.out.println("test=>B");
    }

    public static void main(String[] args) {
        B b=new B();
        b.test();

        A a=new B();
        a.test();//也走了子类的方法
    }
}

20200310学习JAVA笔记:面向对象编程_第7张图片

多态

20200310学习JAVA笔记:面向对象编程_第8张图片

  • 多态是方法的多态,属性是没有多态的。

  • 在父类和子类之间,要有继承关系,方法需要重写。

  • 父类引用指向子类的对象。对象可以调用的方法取决于它引用类型中的方法。

  • static,静态方法属于类,不能被重写。

  • final 常量,不能被重写。

  • private方法是私有,不能被重写。

package oop.Demo07;
public class Person {
    private void read(){
        System.out.println("person reads");
    }
}
/*--------------------------------------------*/
package oop.Demo07;
public class Student extends Person{
    protected void read(){
        System.out.println("student reads");
    }
}
/*--------------------------------------------*/
package oop.Demo07;

public class Application {
    public static void main(String[] args) {
        //一个类的实际对象是确定的,new Student()、new Person();
        // 但可以指向的引用类型的不确定的,可以指向他的任意父类
        //子类能够调用自己的方法或者父类的方法
        Student s1=new Student();
        //父类可以指向子类,但不能调用子类独有的方法
        Person s2 = new Student();//父类的引用指向子类
        Object s3=new Student();//最高父类的引用指向子类
        s1.read();
      //  s2.read();//这里就发生了重写,Persoon类中修饰符不是private,调用的是子类Student的read
                  //如果父类Person方法为private,则不能调用了

        ((Student)s2).read();//此时要调用子类中的read,则需要将s2的引用类型强制转换
    }
}
 

instanceof和类型转换

  • 父类引用可以指向子类对象,子类引用只能指向子类的对象。
  • 子类转换为父类,不用强制转换,向上转型。
  • 父类转换为子类,向下转换,可能丢失方法。
package oop.Demo06;

//B作为子类
public class B extends A {
    
    public static void main(String[] args) {
        B b=new B();
        
        A a=new B();
        System.out.println(b instanceof B);//true
        System.out.println(a instanceof B);//treu
        System.out.println(a instanceof A);//true
    }
}

instanceof用来判断对象和类之间的所属关系。

抽象类与接口

抽象类

  • 抽象类不能new,只能通过它的子类去实现,抽象类本身只提供框架。

  • 抽象类中必须写普通的方法,但抽象方法必须写到抽象类中。

  • 构造函数的作用是用来实例化对象,但抽象类也有构造函数:

    作用是:

    • 初始化抽象类的成员;
    • 为继承自它的子类使用。调用顺序是先调用抽象类的无参构造函数,如果子类实例化时是使用带参的构造函数,则调用抽象类的带参构造函数,最后调用子类本身的构造函数。
package oop.Demo08;
//abstract 抽象类:类 extends:单继承
public abstract class Action {
    //抽象类是提供一种约束和框架,让别人去实现具体的方法
    //抽象方法只有方法名,没有方法的实现,没有方法体;
    public abstract void doSomething();
   //抽象类中可以写普通的方法,但抽象方法必须写在抽象类中;
    public void saySomething(){
        
    }
}

接口

20200310学习JAVA笔记:面向对象编程_第9张图片

  • 接口的本质是一种契约,约束
  • 定义一些方法,让不同的人实现。
  • 接口不能被实例化,接口中没有构造方法。
  • 必须要重写接口中的方法
package oop.Demo09;
//定义接口的关键字:interface
public interface UserService {
    //常量都是public static final
    int age=22;
    //接口中所有定义都是抽象的  public abstract
    void add(String name);
    void delete(String name);
    void updata(String name);
    void quary(String name);
}
/*-----------------------------------*/
package oop.Demo09;

public interface TimerService {
    void timer();
}
/*------------------------------------*/
package oop.Demo09;
//类 用来实现接口  implements
//实现接口中的类,就需要重写接口中的方法
//可以实现多继承
public class UserServiceImpl implements UserService,TimerService{
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void updata(String name) {

    }

    @Override
    public void quary(String name) {

    }

    @Override
    public void timer() {

    }
}

  • 我们不能直接去实例化一个接口,因为接口中的方法都是抽象的,是没有方法体的
  • 一个类可以实现不止一个接口。
  • 一个接口可以继承于另一个接口,或者另一些接口,接口也可以继承,并且可以多继承。
  • 接口中所有的方法都是抽象的和public的,所有的属性都是public,static,final的,常量:public static final; 方法:public abstract;。
  • 接口用来弥补类无法实现多继承的局限。

内部类以及OOP实战

内部类

20200310学习JAVA笔记:面向对象编程_第10张图片

你可能感兴趣的:(20200310学习JAVA笔记:面向对象编程)