Java面向对象编程

视频教程链接


1. 面向过程 & 面向对象

在这里插入图片描述
宏观方面需要面向对象的思想,但是微观就要使用面向过程的思想。


2. 什么是面向对象

在这里插入图片描述
java面向对象编程(oop)

面向对象特征:
在这里插入图片描述


3. 知识回顾 静态方法与非静态方法

修饰符 : static
静态方法:使用static修饰符
在这里插入图片描述

类可以直接调用另外一个类中的静态方法

非静态对象:
在这里插入图片描述
要 new 其他的类后才能使用其中的非静态方法。

在同个类中,不同的静态方法能互相调用,不同的非静态方法也能互相调用,非静态方法可以调用类中的静态方法,但是静态方法不能调用类中的非静态方法,因为二者的加载机制不同,static修饰的静态方法是和当前的类同时加载,非静态方法不是和类同时加载,静态方法相比非静态方法加载的时间要靠前一些。(听了狂神老师的课,这仅是个人理解,后面继续学习会补充这方面的知识)

非静态方法互相调用:
在这里插入图片描述
静态方法互相调用:
在这里插入图片描述
静态方法调用非静态方法:
在这里插入图片描述
非静态方法调用静态方法:
在这里插入图片描述


4. 值传递 引用传递

值传递:

//值传递
public class Demo03 {
    public static void main(String[] args) {
        
        int a = 1;
        System.out.println(a);
        Demo03.change(a);
        
        System.out.println(a);

    }

    public static void change(int a) {
        a = 10;
    }
}

结果:
在这里插入图片描述
发现第二次输出 a 的值并没有发生改变,可见当使用值传递向 change 函数传递变量 a 时,**只是传递了 a 的值。**所以实际参数 a 的值没有改变。

引用传递:

//引用传递
public class Demo04 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);

        Demo04.change(person);
        System.out.println(person.name);

    }
    public static void change(Person person) {
        person.name = "zqy";
    }
    //定义了一个Person类,有个name属性
    static class Person {
        String name;
    }
}

运行结果:
在这里插入图片描述
change 函数中传递的参数是 Person 并且该函数修改了 Person 函数中的属性 name。


5. 类与对象的关系

在这里插入图片描述
在这里插入图片描述


6. 创建与初始化对象

在这里插入图片描述

使用 new 创建对象

public class Application {
    //一个项目应该只有一个main方法
    public static void main(String[] args) {

        //使用 new 对抽象的类进行实例化
        Student zns = new Student();
        Student zqy = new Student();

        zns.name="伞兵1号";
        zns.age=1;
        System.out.println(zns.name);
        System.out.println(zns.age);
        zqy.name="伞兵2号";
        zqy.age=2;
        System.out.println(zqy.name);
        System.out.println(zqy.age);
    }
}
//学生类
public class Student {
    //属性,字段
    String name;
    int age;

    //方法
    public void study() {
        System.out.println(this.name + "在学习!!");
    }
}

7. 构造器

在这里插入图片描述
先写个方法,里面啥也不加:

public class Person {
}

使用另外一个启动类的main方法实例化并启动:

public class Application {

    public static void main(String[] args) {

        //使用 new 对抽象的类进行实例化
        Person person = new Person();
    }
}

发现成功运行,没有报错。
查看Person的编译文件:
在这里插入图片描述
和java文件对比,发现被自动添加了一个方法,这个方法就是构造方法。

也可以手动写显示构造器:(无参构造器)

public class Person {
    public  Person(){
        
    }
}
构造器作用

1.实例化初始值(为变量进行初始化)

public class Person {
    String name;

    public Person() {
        this.name = "zqy";
    }
}

2.使用 new 时,本质是去自动调用类中的构造器

注意:如果定义了有参构造,就一定要写显示构造器(否则会报错):
在这里插入图片描述
写了显示构造后:
在这里插入图片描述

idea 生成构造器快捷键 alt+ins
在这里插入图片描述

在这里插入图片描述

构造器重载:
在这里插入图片描述


8. 创建对象简单内存分析

Application类:

public class Application {
    public static void main(String[] args) {
        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 3;
        System.out.println(dog.name);
        System.out.println(dog.age);


        Pet cat = new Pet();
        

    }
}

Pet类:

public class Pet {

    String name;
    int age;
    public void  shout(){
        System.out.println("叫了一声");
    }
}

1.当使用 new 去实例化一个对象时,先经过方法内的无参构造
2.加载类,加载类中的main方法、常量
3.执行main方法,将main方法压入到栈中(main方法是最先被压入栈的,所以说,当栈中的main方法被释放后,就可以认为这个方法已经结束)
在这里插入图片描述
4.加载 new 的类(实例化),加载被实例化类的属性和方法(类似于加载这个类,并把它当做模板,通过这个模板生成一个对象)
例:当 new 一个dog时,第一步,在堆中分配各 new 的这个方法一块内存并分配地址,将模板存入这个内存,第二步,将dog压入栈,并指向堆中分配的内存块
在这里插入图片描述
5.进行赋值时,堆中的变量直接引用方法中传入的值。由于shout( ) 没有参数,所以直接调用Pet类中的方法。
在这里插入图片描述
6.当又new了一个cat,同样,先在栈内分配内存获取地址,并且存入模板。栈内压入cat。并指向堆内的新分配的堆内存。
在这里插入图片描述

总体:
在这里插入图片描述


9. 封装

主要思想:
在这里插入图片描述

关键字: privatepublic对应
私有化的属性不能直接通过实例化后的方法进行访问,需要使用get和set方法。

使用get和set
idea 自动生成get、set方法(快捷键 alt+ins):
在这里插入图片描述

set方法,给这个变量赋值,get方法获取到这个变量的值

//private 属性私有
public class Student {

    private String name;
    private int id;

    //需要提供一些可以操纵这些属性的方法 get/set

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
public class Application {
    public static void main(String[] args) {

        Student s1 = new Student();
        s1.setName("马牛逼");
        System.out.println(s1.getName());

    }
}

结果:
在这里插入图片描述

通过 get set 方法能够对数据进行过滤:

public class Application {
    public static void main(String[] args) {

        Student s1 = new Student();

        s1.setAge(500);
        System.out.println(s1.getAge());

    }
}
public class Student {

    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 120 || age < 0) {
            this.age = 3;
        } else {
            this.age = age;
        }
    }
}

封装的意义:

  1. 提高安全性,可以保护数据
  2. 隐藏代码的细节
  3. 统一接口
  4. 提高系统的可维护性

10. 继承

在这里插入图片描述

public class Person {
    //人
}
public class Teacher extends Person{
}
public class Student extends Person{
}

Person是父类(基类),其他两个Student和Teacher是子类(也可以叫派生类)

被final修饰的方法不能被继承(final之后断子绝孙了)

查看类继承树状图:
idea快捷键 ctrl + H
在这里插入图片描述

注意:所有的类都默认继承了Object类
在这里插入图片描述


11. Super详解

this关键字是一对,this代表当前的类,super代表父类

访问父类变量:

在这里插入图片描述

代码:

public class Person{
    protected String name = "zqy1";
}
public class Student extends Person {
    private String name = "zqy2";

    public void say(String name) {
        System.out.println(name);
        System.out.println(this.name);//访问自身属性
        System.out.println(super.name);//访问父类属性
    }

}
public class Application {
    public static void main(String[] args) {
        Student student1 = new Student();
        student1.say("zqy3");
    }
}

访问父类方法:

在这里插入图片描述

代码:

public class Person{
  public void print(){
      System.out.println("我是父类");
  }
}
public class Student extends Person {

    public void print() {
        System.out.println("我是子类");
    }

    public void test() {
        print();
        this.print();
        super.print();
    }
}
public class Application {
    public static void main(String[] args) {
        Student student1 = new Student();
        student1.test();
    }
}

注意:私有属性(private)无法被继承。
在这里插入图片描述

子类默认调用了父类的无参构造
例:
在这里插入图片描述

super( ); 默认隐性使用,如果要显性使用,就必须要在子类的第一行。

在这里插入图片描述

在这里插入图片描述

同样当使用this( );调用本类的构造参数时,也要在第一行。
在这里插入图片描述

啊这。。。。遇见问题了:这该如何是好
在这里插入图片描述
在这里插入图片描述
太菜了没见过。。。。。。

当使用super( ) ;调用有参构造时,要传入参数:
在这里插入图片描述
写完有参就没有无参了

在这里插入图片描述


12. 方法重写

重写是方法的重写,与属性无关。
只有非静态方法才能重写。

在这里插入图片描述

public class B {
     public  void test(){
        System.out.println("B");
    }
}
public class A extends B{

     @Override
    public void test() {
       //在这里重写父类的 test()方法
        System.out.println("我很牛");
    }
}

执行结果:
在这里插入图片描述

当使用static静态方法时:
在这里插入图片描述
小结:当使用static修饰方法时,方法调用只与new方法左边的有关,例如上图,分别使用B和A去new一个A方法,并调用其中的test()方法,结果是分别调用了属于左边类的方法(A调用了A中的test,B调用了B中的test)并没有进行重写操作。当不使用static修饰后,才会进行方法重写。(要进行重写的方法的修饰符必须为public)
在这里插入图片描述


在这里插入图片描述


13. 什么是多态

在这里插入图片描述
在这里插入图片描述

例:

public class Student extends Person {
//子类
}
public class Person{
//父类
}
public class Application {
    public static void main(String[] args) {

        //一个对象的实际类型是确认的(Student对应Student,Person对应Person)
        Student s1 = new Student();
        Person p1 = new Person();

        //可以指向的引用对象类型就不确定了:父类引用指向子类
   		Student s2 = new Student();
        Person s3 = new Student();
        Object p2 = new Person();
    }
}

同时调用一个方法,如果子类没有重写,就调用父类中该方法,如果子类进行重写,就调用子类重写后的方法。

在这里插入图片描述
在这里插入图片描述


例2:
代码:

public class Person {
    public void run() {
        System.out.println("父");
    }
}
public class Student extends Person {
    @Override
    public void run() {
        System.out.println("子");
    }

    public void eat() {
        System.out.println("吃");
    }
}
public class Application {
    public static void main(String[] args) {


        //Student可以调用的方法:自己独有的或者继承的方法
        Student s2 = new Student();
        //Person 父类型:可以指向子类,但不能调用子类独有的方法
        Person s3 = new Student();
        Object p2 = new Person();


        //对象能执行哪些方法,主要看等于号左边的类型,和右边的关系不大
        s2.eat();
        
        //父类型不能直接调用子类特有的方法,如果要调用,要进行强制类型转换
        s3.eat();
        ((Student) s3).eat();

        //子类重写了父类的方法,所以当父类调用这个被重写的方法是直接调用自子类重写后的方法
        s2.run();
        s3.run();
    }
}

运行结果:
在这里插入图片描述

小结:(staticfinalprivate修饰的方法不能被重写)
在这里插入图片描述
再次强调:只有方法有多态,属性没有多态。

多态教学视频


14. instanceof关键字

用来判断两个类之间是否存在父子关系(继承关系)

例:

public class Student extends Person {
    //子类
}
public class Teacher extends Person{
    //子类
}
public class Person{
//父类
}
public class Application {
    public static void main(String[] args) {

        /*
        继承关系
        Object > String
        Object > Person > Teacher
        Object > Person > Student
        */

        Object o1 = new Student();
        System.out.println(o1 instanceof Student);
        System.out.println(o1 instanceof Person);
        System.out.println(o1 instanceof Object);
        System.out.println(o1 instanceof Teacher);
        System.out.println(o1 instanceof String);

        Person p1= new Student();
        System.out.println(p1 instanceof Student);
        System.out.println(p1 instanceof Teacher);
        System.out.println(p1 instanceof Object);
//        System.out.println(p1 instanceof String);//编译报错
    }
}

总结公式:
X instanceof Y,当X和Y之间存在继承关系则该关系式的值为true。

类型转换

与变量类型转换原理相同,父类向子类转换(高 --> 低)需要强制类型转换,可能会导致子类的一些方法丢失,反之则不需要。

public class Student extends Person {
    //子类
    public void go(){
        System.out.println("go");
    }
}
public class Application {
    public static void main(String[] args) {


        Person s1 = new Student();
        //s1类型为Person,是Student的父类,所以,当s1要调用子类Student中的go方法时,要进行强制类型转换
        ((Student) s1).go();


        //子类转化为父类,低-->高 直接转化
        Student s2 = new Student();
        s2.go();
        Person p1 = s2;
    }
}

小结:
在这里插入图片描述


15.static关键字

1. 可以使用类名直接访问static修饰的变量(静态变量)
public class Student {
 	private static int age;//静态变量
    private double money;//非静态变量

    public static void main(String[] args) {
        Student s1 = new Student();

        System.out.println(Student.age);
        System.out.println(s1.age);
        System.out.println(s1.money);
    }
}

不能通过类名访问非静态变量
在这里插入图片描述

同样,静态方法也可以这么调用:

public class Student {


    public void run() {//非静态方法
    }

    public static void go() {//静态方法
    }


    public static void main(String[] args) {
        new Student().run();
        Student.go();
        go();//还可以直接调(因为是在当前的类中)
    }
}

在这里插入图片描述
静态方法能调用静态方法,非静态方法可以调用静态方法和非静态方法

2. 代码块
public class Person {

    {
        //匿名代码块
    }

    static {
        //静态代码块
        //和类同时加载,只生效一次
    }
}

代码块、静态代码块、构造方法三者的加载顺序:

public class Person {

    //第二执行
    {
        //匿名代码块
        System.out.println("匿名代码块");
    }

    //最先执行
    static {
        //静态代码块
        //和类同时加载,只生效一次
        System.out.println("静态代码块");
    }

    //最后执行
    public Person() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        new Person();
    }
}

在这里插入图片描述

再次new一个Person:
在这里插入图片描述
在这里插入图片描述
静态代码块只执行了一次

静态代码块的作用
赋初始值

3.静态导入包

例:
当我们要使用java封装好的方法时(以随机数生成为例)
在这里插入图片描述
需要输入 Math.random();非常的麻烦,
我们可以通过import直接导入Math包的random:
在这里插入图片描述

//静态导入
import static java.lang.Math.random;

public class Test {

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

但是这种方法不怎么用…


16. 抽象类

在这里插入图片描述
写一个抽象类:

//abstract 修饰抽象类
public abstract class Action {

    //abstract 抽象方法,只有方法名,没有方法的实现
    public abstract void doSomthing();
}

子类如果继承抽象类,就必须重写里面的方法:

在这里插入图片描述

在这里插入图片描述

//抽象类的所有方法必须要由子类实现(重写)
public class A extends Action{
    @Override
    public void doSomthing() {
        
    }
}

如果继承抽象方法的子类也是一个抽象方法,就不需要重写里面的方法,就会让一个不是抽象方法的子类(或者子类的子类)去重写


小结:
在这里插入图片描述
抽象类提高开发效率,将一些常用的变量进行抽象类封装

再看看抽象类有没有构造方法:
在这里插入图片描述
这个还真有。


17. 接口

在这里插入图片描述

//通过interface关键字定义接口
public interface UserServer {
    
    //接口中的所有定义都是抽象的 默认已经有public abstract了,所以写上会变成灰色
    public abstract void run();
    
    //也可以直接省略public abstract
    void run2();
}

接口只是起到定义方法的作用,要实现方法还需要一个实现类

定义一个实现类,命名规范,一般要在实现类的名后添加一个Impl:
通过implements关键字链接定义好的接口,并重写接口中定义的方法

public interface UserServer {

    void insert();
    void delete();
    void update();
    void query();
}
public class UserServerImpl implements UserServer{
    @Override
    public void insert() {

    }

    @Override
    public void delete() {

    }

    @Override
    public void update() {

    }

    @Override
    public void query() {

    }
}

一个类可以链接多个接口:接口之间用逗号分隔。
在这里插入图片描述

接口从侧面实现了extends无法实现的多继承。
如果在接口中定义常量:

public interface UserServer {

    //默认接口中定义的是常量public static final
    public static final int age=99;
    
    //也可以省略public static final 也是默认常量
    int ages=100;
    
    
    void insert();
    void delete();
    void update();
    void query();
}

在这里插入图片描述
一般不用

在这里插入图片描述


18. 内部类

在这里插入图片描述

1. 成员内部类

例:

public class Outer {

    private int age;
    public void out(){
        System.out.println("这是外部类方法");
    }

    public class Inner{
        public void in(){
            System.out.println("这是内部方法");
        }
    }
}
public class Application {

    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.out();

        //通过这个外部类来实现内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();

    }
}

在这里插入图片描述

可以通过内部类来获取到外部类的私有属性
在这里插入图片描述

2. 静态内部类

通过static修饰的内部类
在这里插入图片描述

3. 局部内部类
public class Outer {

    //局部内部类
    public void methon() {
        class A {
            public void in() {
    
            }
        }
    }

}

扩展:

public class Outer {


}

//一个java类中可以有多个class类,但是只能有一个public修饰的class类
class A{
    public static void main(String[] args) {
        
    }
}

在这里插入图片描述

4. 匿名内部类
public class Outer {

    public static void main(String[] args) {

        //没有名字的初始化类和接口,不需要将实例保存在变量中
        new A().eat();

        //会返回一个UserServer的对象
        UserServer userServer = new UserServer() {

            @Override
            public void run() {

            }
        };
    }
}

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

interface UserServer {
    void run();
}

在这里插入图片描述


  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

覅乆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值