【系统学习】【Java基础】2-Java进阶知识总结-1-面向对象

Java SE进阶知识总结-1

面向对象-1-【基础、封装】

基本概念

类和对象的概念

类和对象概念的理解相辅相成:

  • 类:是一个模板,描述一类对象的行为(成员方法)和状态(成员属性)、
  • 对象:对象是类的一个实例(一个类可以有多个对象,想要创建对象,必须现有类的存在),有相应的行为和状态

类的组成

属性,称为:成员变量

方法,称为:成员方法

成员变量和局部变量的区别

image-20231007101254431

this关键字

  • this:代表当前类对象的引用,是一个地址值
  • 用途:当局部变量和成员变量出现了重名的情况,java采用就近原则,使用局部变量,通过this关键字,可以让其使用成员变量
public class Account {
    private String name;
    private double balance;
    private String pwd;
	
	//Account类的一个构造器
	public Account (String name,double balance,String pwd){
		//构造器的实现---初始化对象
		this.name = name;
		this.balance = balance;	
		this.pwd = pwd;
	}
}

构造方法

什么是构造方法?

  • 构建、创造对象的时候,所调用的方法

构造方法的用途?

  • 可以用来给对象中的属性进行初始化赋值

构造方法的类别?

  • 有两种:无参构造和有参构造
  • 无参构造只能有一个;有参构造可以有多个
public class Student {

    String name;
    int age;

	// 无参构造
    public Student() {
    }

    // 带参构造:2个参数
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

构造方法的特点?

  • 方法名与类名一样
  • 只有一个权限修饰符和方法名:没有返回值类型(void也没有);没有具体返回值(return也没有)

构造方法的执行时机?

  • 创建对象的时候调用,每创建一次,执行一次构造方法

构造方法有哪些特点?

  • 不能手动调用构造方法

  • 系统默认提供无参构造方法

  • 人工定义了有参构造方法,系统就不提供无参构造了,需要自行定义出无参构造

  • 构造方法支持重载

封装【对象三要素之一】

什么是封装?

  • 使用类设计对象时,将需要处理的数据(成员变量)以及处理这些数据的方法(成员方法),设计到对象中

封装要素

合理隐藏、合理暴露。不要过度封装

权限修饰符

public、protected、private

image-20231006214620686

面向对象-2-【static、final、继承】

static关键字

常规理解一个东西的步骤:是什么?有什么特点?有什么注意事项?有什么用途?

static关键字的用法?

  • 静态的意思,可以用于修饰成员变量,也可以修饰成员方法

被static修饰的成员(变量、方法),具有哪些特点?

  • 该成员可供该类的所有对象共享

  • 多了一种调用该成员的方式:

    • 正常调用方式:实例化对象调用(new一个对象)
    • 多个调用方式:直接通过类名调用【被static修饰的成员,推荐使用这种方法调用】
  • 随着类的加载而加载,优先于对象存在

    • 即使没有实例化对象,也可以访问到该成员

若成员方法被static修饰,需要注意如下:

  • 方法中只能访问静态成员【包括成员变量和成员方法】:可能当类加载的时候,还没有初始化对象,因此不能访问非静态的成员

  • 方法中不允许使用this关键字:当类加载的时候,对象可能还没有创建,因此不能使用this

static关键字的用途?

  • 用来修饰成员变量,使得该变量可以成为共享数据的载体,被所有对象调用
  • 用来修饰成员方法,常用于工具类,类似System等模块(所有的方法都被static修饰),不需要(也不可以)实例化对象,仅提供方法供访问

final关键字

final关键字的用法?

  • 最终的意思,可以用来修饰类、方法、变量

被final修饰的对象的特点?

  • 被修饰的类:是最终类,不能被继承

  • 被修饰的方法:是最终方法,不能被重写

  • 被修饰的变量:

    • 是基本数据类型:该变量是常量,不能再被赋值
    • 是引用数据类型:地址值不可以变,但其中的内容可以变

被final修饰的变量的命名规范?

  • 单个词:纯大写
  • 多个词:纯大写且每个词中间用下划线连接

被final修饰的变量的初始化时机?

  • 在变量定义的时候
  • 在构造方法初始化的时候

继承

什么是继承?

  • 继承就是子类拥有父类的特征和行为,具备父类的属性和方法

什么时候使用继承?

  • 当类与类之间,存在相同的内容,并且具有 is a的关系【是xxx的一个xxx】,就可以考虑使用继承

为什么要使用继承?

  • 提高代码的重用性
  • 优化代码,修改方便
  • 类与类之间产生关系,是多态的前提

Java中怎么实现继承?

  • 通过extend关键字来实现

Java中继承的特点?

  • Java只支持单继承,不支持多继承,但支持多层继承

  • 继承关系中的成员变量:

    • 子类和父类中出现重名的变量,就近原则,子类优先使用自己的变量。若要用父类变量:super.变量名
    • 该用法同this一样:this指向该类地址;super指向父类地址
  • 继承关系中的成员方法:

    • 在子类中运行父类的方法:super.method()
    • 在子类中重写父类的方法:(1)保证方法声明一致:方法名、参数、返回值类型均一致;(2)若要判断是否是重写,可以用@override装饰器装饰一下
  • 继承关系中的构造方法:

    • 子类的构造过程中必须调用基类的构造方法
    • 若显式调用基类的构造方法,必须放在子类构造方法的第一行
    • 若无显式调用基类的构造方法,则默认调用基类的空参构造方法(基类无空参构造方法会报错)

继承关系中的内存关系?

  • 图解

image-20231007182516874

  • 子类在初始化的时候,会在其内存空间留一块存储父类数据的内存
  • 该块内存可以被继承到,但是会根据权限修饰符的不同,有时不具备对其的访问条件【一定能继承到,不一定能访问到】

this和super的区别?

image-20231007182555010

面向对象-3-【包、抽象类、接口、多态】

什么是包?

  • package,本质就是文件夹,管理Java类的文件夹

怎么建包?

package 公司域名倒写.技术名称			// 全部小写,且具有意义。package后面所有的内容都是包名

// 建包语句必须在文件第一行写出【IDEA工具默认会给出建包语句】

怎么导包?

  • 相同包下的类可直接访问,不同包之间的类访问才需要导包:import 包名.类名
  • 假如一个包中的两个类,他们名字一样,还都被另一个类用到了。
    • 此时,只能通过导包的方式导入一个类,导入后可仅通过类名访问
    • 另一个类需要带包名访问,不能只通过写类名访问

抽象类

什么是抽象类?

  • 抽象类是特殊的父类,内部写有抽象方法
    • 抽象方法:将共性的行为抽象到父类中,发现其实现逻辑无法明确给出,就只定义方法,具体逻辑,由继承抽象类的子类实现
    • 如果一个类中有抽象方法,该类就必须声明为抽象类

抽象类的定义格式?

// 抽象类
public abstract class 类名{};

// 抽象方法
public abstract 返回值类型 方法名(参数列表);

抽象类有什么注意事项?

  • 自身:不能实例化;存在构造方法,可供子类访问;类中可以编写普通方法
  • 对于继承抽象类的子类:要么重写所有抽象方法,成为普通类;要么依旧是抽象类

接口

接口相关概念

什么是接口?

  • 是一个抽象类型,是抽象方法的集合,体现的思想是对规则的声明
  • 在Java中,接口体现为对行为(方法)的抽象

接口命名规范?

public interface 接口名{}

接口有什么特点?

  • 自身:不能被实例化,且内部全是抽象方法
  • 继承接口的子类:要么重写所有抽象方法,成为普通类;要么重写部分抽象方法,成为抽象类

接口的内部成员有什么特点?

  • 成员变量:只能是常量【默认提供修饰符:public static final
  • 构造方法:没有构造方法【继承接口的实现类里面的构造方法,访问的是objects类的父类构造方法,而不是接口的构造方法】
  • 成员方法:只能是抽象方法【默认提供修饰符:public abstract

普通类和接口间的相互关系

类和类之间?

  • 继承关系,仅单继承和多层继承,不可多继承

类和接口之间?

  • 实现关系:可以单实现、可以多实现、可以在继承的同时多实现
// 单实现
public class 类名 implements A {}

// 多实现
public class 类名 implements A, B {}

// 继承中多实现
class Zi extends Fu implements A, B {}

接口和接口之间?

  • 继承关系,可以单继承,也可以多继承
    • 可以多继承的原因是:接口中全是抽象方法,就算不同的父类中有一样的方法名,继承哪一个也都无所谓
    • 类不能多继承的原因是:父类中若有相同的方法,不知道该继承哪一个(python中是就近原则,所以python支持多继承)

抽象类和接口间的相互关系

两者成员变量间的区别?

  • 抽象类:可以定义常量,可以定义变量
  • 接口:只能定义常量

两者成员方法间的区别?

  • 抽象类:可以定义具体方法,也可以定义抽象方法
  • 接口:只能定义抽象方法

两者构造方法的区别?

  • 抽象类:有构造方法
  • 接口:没有构造方法

接口新特性-Java8

Java8中新的接口特性?

  • 允许在接口中定义默认方法和静态方法

默认方法和静态方法的定义格式?

public interface MyInterface {
    // 默认方法的定义格式
    public default void myMethod() {}
    
    // 静态方法的定义格式
    public static void myStaticMethod() {}
}

新特性的应用场景?

  • 默认方法(可被重写):
    • 解决接口升级的问题。以往都是抽象方法,接口引入新的抽象方法后,所有的实现类中都要重写新的方法,影响范围极大
    • 有了默认方法后,已经实现该接口的实现类,不需要再改动代码;新的实现类,可以重写新增的默认方法
  • 静态方法(不可被重写):
    • 解决接口升级的问题。常规,同上
    • 可以在不重写且不增加实现类的基础上,直接接口.方法的调用形式,提供新的功能

新特性的注意事项?

  • 默认方法不是抽象方法,不强制重写【可以重写,重写之后记得去掉default关键字即可】
  • 默认方法中的public关键字可以省略,default关键字不可以省略
  • 如果实现了多个接口,且接口中有相同的方法声明,子类就必须对该方法进行重写【强制】

接口新特性-Java9

Java9中的接口新特性?

  • 允许定义私有(静态)方法

私有(静态)方法的定义格式?

public interface MyInterface {
    // 私有方法的定义格式
    public private void myMethod() {}
    
    // 静态私有方法的定义格式
    public private static void myStaticMethod() {}
}

私有(静态)方法的定义格式?

  • 静态方法逻辑已经写完了,即不可重写
  • 私有静态方法只能在接口内部调用

多态

什么是多态?

同一个行为具有多个不同表现形式或形态的能力,称为多态

多态的实现前提?

1、有继承或实现

2、有方法重写

abstract class Animal {
    public abstract void eat();
}
// 有继承
class Dog extends Animal {

    // 有方法重写
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}
class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

3、有父类引用(等号左边)指向子类对象(等号右边)

package com.itheima.polymorphism;

public class PolymorphismTest1 {
    public static void main(String[] args) {
        // 有父类引用指向子类对象  
        Animal a = new Dog();
        useAnimal(a);

        useAnimal(new Cat());
    }

    public static void useAnimal(Animal a) {        // Animal a = new Dog();
          a.eat();                                  // Animal a = new Cat();
    }
}

【补充】子类引用指向子类对象:Dog a = new Dog();

**多态的效果就是:**同一个表现吃的代码,输入对象不同,吃的结果也不同

多态的成员访问特点

非静态成员

  • 访问成员变量:编译看左边(看父类是否有该成员),执行看左边(执行父类的成员变量)
  • 访问成员方法:编译看左边(看父类是否有该方法),执行看右边(执行子类的成员方法,不执行父类的方法,防止该方法是一个抽象方法)

静态成员

  • 推荐使用类名.成员调用。即使使用对象实例调用这种方法,在.class编译的时候也会变为类名调用
  • 不管是成员变量或成员方法,都是调用的左边的【父类的】(静态的成员方法,不用担心是抽象方法的问题,都是调用左边的)

体现成员访问特点的示例

class Fu {
    int num = 10;

    public void show() {
        System.out.println("Fu...show");
    }

    public static void print(){
        System.out.println("Fu...print");
    }
}
class Zi extends Fu {
    int num = 20;

    @Override
    public void show() {
        System.out.println("Zi...show");
    }

    public static void print(){
        System.out.println("Zi...print");
    }
}
package com.itheima.polymorphism;

public class PolymorphismTest2 {
    public static void main(String[] args) {
        // 多态
        Fu f = new Zi();		
        
        // 结果:10
        // 访问成员变量,编译输出均看左边,输出父类中的值
        System.out.println(f.num);
        
        // 结果:Zi...show
        // 访问非静态成员方法,编译看左边:字节码文件中是zi.show();执行看右边:输出结果是子类中的值
        f.show();					
        
        // 结果:Fu...print
        // 访问静态成员方法,编译看左边:字节码文件中是Fu.print();执行看右边:输出结果是父类中的值
        f.print();
    }
}

多态的好处与不足?

好处:提高程序的扩展性

  • 对象多态:将方法的形参定义为父类类型,这个方法可以接受该父类的任意子类类型
  • 行为多态:同一个行为具有多个不同表现形式或形态

不足

  • 不能使用子类的特有成员:因为编译都是看左边,子类的特有成员,父类不具备,编译就不通过

多态中的转型问题

向上转型【父类引用指向子类对象】

FU f = new Zi();

向下转型【子类引用指向父类对象】

Zi z = (Zi)f;

示例

package com.itheima.order;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:  1. 国内订单   2. 国外订单");

        OrderService orderService = null;

        int choice = sc.nextInt();
        switch (choice) {
            case 1:
                // 创建国内订单的业务类
                orderService = new OrderServiceImpl();		// 向上转型
                break;
            case 2:
                // 创建国外订单的业务类
                orderService = new OverseasServiceImpl();	// 向上转型
                break;
        }

        // instanceof : 判断左边的引用, 是否是右边的数据类型
        if(orderService instanceof OverseasServiceImpl){
            OverseasServiceImpl osi = (OverseasServiceImpl) orderService;	// 向下转型
            osi.check();	// OverseasServiceImpl子类对象特有的方法
        }

        orderService.create();
        orderService.findOne();
        orderService.findList();
        orderService.cancel();
        orderService.finish();
        orderService.paid();
    }
}

instanceof关键字

  • 用途:判断一个对象是不是一个类的实例

  • 用法:实例对象 instanceof 类名

面向对象其他知识-4-【代码块、内部类、Lambda表达式】

代码块

局部代码块

定义位置:方法中定义

作用:可以限定生命周期,提早释放(现在电脑内存普遍比较大,不怎么用这个)

public class BlockTest {
    public static void main(String[] args) {
		// 内部代码块
        {
            int num = 10;
            System.out.println(num);
        }
        xxx;
        xxx;
    }
}

构造代码块

位置:在类中的方法外定义

特点:每次构造方法执行,该代码块就会在构造方法执行前进行执行

好处:提高构造方法中代码的复用性

class Student {
    {
        System.out.println("Student类的构造代码块");
        System.out.println("好好学习");
    }

    public Student(){
        System.out.println("空参构造方法...");
    }

    public Student(int num){
        System.out.println("带参构造方法...");
    }

}

静态代码块

位置:类中的方法外定义

特点:需要static关键字修饰,随着类的加载而加载,只执行一次

好处:在类加载的时候做一些数据初始化的操作

class Student {
    // 静态代码块
    static {
        System.out.println("静态代码块");
    }
    
    // 构造代码块
    {
        System.out.println("构造代码块");
    }

    public Student(){
        System.out.println("空参构造方法...");
    }

    public Student(int num){
        System.out.println("带参构造方法...");
    }
}

静态代码块和构造代码块所处的位置是一样的,都是在类中的方法外,区别在于一个有static修饰,另一个没有

同步代码块

后续再说

内部类

定义在类里面的类

成员内部类

**创建位置:**定义在类中方法外的一个类

成员内部类定义示例及成员访问

class MyOuter {
    int num = 10;

    class MyInner {

        int num = 20;

        public void show(){
            int num = 30;

            System.out.println(num);                            // 30
            System.out.println(this.num);                       // 20
            System.out.println(MyOuter.this.num);               // 10
        }
    }
}

成员内部类的实例化对象创建格式

外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();

Outer.Inner in = new Outer().new Inner();

成员访问特点

  • 内部类访问外部类成员:直接访问,包括私有(创建内部类的时候,外部类一定有创建)
  • 外部类访问内部类成员:需要创建对象访问(创建外部类的时候,内部类不一定有创建)
class Outer {

    private void method(){
        System.out.println("method...");

        Inner i = new Inner();
		// 外部类访问内部类成员
        System.out.println(i.num);
    }

    class Inner {
        int num = 10;

        public void show(){
            System.out.println("show...");
            // 内部类访问外部类成员
            method();
        }
    }
}

静态内部类

**创建位置:**定义在类中方法外的一个类(静态内部类就是static修饰的成员内部类)

静态内部类的实例化对象创建格式

外部类名.内部类名 对象名 = new 外部类名.内部类对象();

Outer.Inner in = new Outer.Inner();  // 这里Outer后面没有括号

成员访问特点

  • 内部类访问外部类成员:

    • 外部类的静态成员变量,可以直接访问
    • 外部类的非静态成员变量,需要创建外部类对象后再访问(类加载的时候,静态内部类就创建了,此时外部类还没创建,因此要访问,需要先创建对象)
  • 外部类访问内部类成员:需要创建对象访问?【暂时存疑】

class OuterClass {

    int num1 = 10;
    static int num2 = 20;

    static class InnerClass {

        public static void show(){
            System.out.println("show...");

            OuterClass o = new OuterClass();
            System.out.println(o.num1);

            System.out.println(num2);
        }
    }
}

局部内部类

**局部内部类的创建位置:**方法、代码块、构造器等执行体中

class A {
    public void show(){
        class B {
            public void method(){
                System.out.println("method...");
            }
        }

        B b = new B();
        b.method();

    }
}

局部内部类的成员访问特点?

  • 只能在方法内、代码块、构造器内部访问
  • 访问前需要先创建对象,再访问

匿名内部类

什么是匿名内部类? 匿名内部类本质是一个特殊的局部内部类(定义在方法内部)

**匿名内部类的前提:**需要存在一个接口或类,才能写匿名内部类

**匿名内部类的特点:**可以使代码简洁,在定义一个类的同时对其进行实例化

定义格式

new 类名\接口名 () {

}

// new 类名(){} : 代表继承这个类
// new 接口名(){} : 代表实现这个接口(需要重写里面所有的抽象方法)

示例

  • 有一个接口
interface Inter {
    void show();
}
class InterImpl implements Inter {
    @Override
    public void show() {
        System.out.println("InterImpl...show...");
    }
}
  • 匿名内部类
public class AnonClassTest1 {
    public static void main(String[] args) {

        // 问题: 方法的形参是接口类型, 我们该传入的是什么?
        // 答案: 传入的是该接口的实现类对象
        
        // 不适用匿名内部类:需要借助接口实现来完成
 		// 暗含着:父类引用指向子类对象
        useInter(new InterImpl());

        // 使用匿名内部类:不需要额外写接口的实现,直接定义匿名内部类,即可完成功能
        useInter(new Inter(){

            @Override
            public void show() {
                System.out.println("匿名内部类...show...");
            }
        });

    }

    public static void useInter(Inter i){
        i.show();
    }
}

Lambda表达式

简化匿名内部类的写法

正常写匿名内部类,鼠标移动到匿名内部类()里面,alt+enter,一键修改为lambda表达式

Lambda表达式和匿名内部类的区别

使用限制不同

  • 匿名内部类 : 可以操作类、接口
  • Lambda表达式 : 只能操作函数式接口(只有一个方法的接口、类)

实现原理不同

  • 匿名内部类:编译之后,产生一个单独的.class字节码文件
  • Lambda表达式:编译之后,没有一个单独的.class字节码文件

函数式接口、匿名内部类的区别、Lambda表达式

  • 函数式接口是指只有一个方法(函数)的接口
  • 匿名内部类可以简化接口的写法
  • 当匿名内部类的接口是函数式接口,可以写为lambda表达式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值