目录

面向对象


面向对象

1 面向对象和面向过程的区别

1.1 都是编程思想

1.2 面向过程注重过程,步骤,怎么做

  • 执行者

1.3 面向对象注重对象,谁来做

  • 指挥者

2 面向对象学习

2.1 、类与对象

  • (1)类与对象的概念
  • (2)类与对象的关系
  • (3)如何设计类,类的成员
  • (4)如何创建对象

2.2 、面向对象的三个基本特征和高级特性

  • 基本特性

    • 封装
    • 继承
    • 多态
  • 高级特性

    • 枚举
    • 接口
    • 抽象
    • 泛型
    • 注解
    • 可变参数
    • 自动装箱与拆箱
    • foreach
    • Lambda表达式
    • …..

2.3 、相关的关键字和API

  • 关键字

    • class

    • new

    • this

    • 权限修饰符

      • public
      • protected
      • 缺省
      • private
    • super

  • API

    • 集合
    • 异常
    • IO
    • 网络编程
    • 线程
    • ….

3 、类与对象

3.1 (1)类与对象的概念

  • 类:对一类具有相同特征的事物的抽象描述
  • 对象:类的实例,是具体的个体

3.2 (2)类与对象的关系

  • 类是对象的设计图,创建的模板
  • 对象是类的实例,是一个具体的个体

3.3 (3)类的设计,成员

  • (1)属性

    • 属性的特点

      • (1)声明的位置

        • 在类中方法外
      • (2)保存的位置

        • static

          • 在方法区
        • 非static

          • 在堆中
      • (3)默认值

        • byte,short,int,long是0,float,double是0.0,boolean是false,char是\u0000,引用数据类型都是null
      • (4)作用域

        • 在整个类中
      • (5)生命周期

        • 随着对象的创建而创建,到垃圾回收为止
    • 属性声明格式

      • [修饰符] 数据类型 属性名 【=显式值】;

        • 修饰符

          • private

            • 私有化
  • (2)构造器

    • 构造器的作用

      • (1)和new一起创建对象
      • (2)为属性赋值
    • 如何声明

      • 无参

        • [修饰符] 类名(){ }
      • 有参

        • [修饰符] 类名(形参列表){ }
    • 特点

      • 构造器的特点: (1)构造器名与类名必须相同 (2)构造器没有返回值 (3)构造器可以重载 (4)如果一个类没有声明过构造器,编译器将默认添加一个无参构造 如果这个类声明了构造器,编译器将不再自动添加无参构造
    • 如何调用

      • (1)和new一起

        • new 构造器() new 构造器(实参列表)
      • (2)在本类的其他构造器中或子类的构造器中

        • 在本类的其他构造器中:this()或this(实参列表) 在子类的构造器中:super()或super(实参列表)
  • (3)方法

    • 无参无返回值
    • 有参无返回值
    • 无参有返回值
    • 有参有返回值
  • (4)代码块

    • 按位置分

      • 在类中方法外

        • 是否有static修饰

          • 有static修饰的:静态代码块

            • 语法结构

              • class 类{ static{ 静态代码块 } }
            • 特点

              • 随着类的加载并初始时而执行,而且一个类的静态代码块只执行一次

                • 而且父类的静态代码块优先于子类的静态代码块
                • 静态代码块肯定优先于构造块和构造器
            • 作用

              • 为静态变量(类变量)初始化(赋值)
          • 没有static修饰的:非静态代码块,构造块

            • 语法结构

              • class 类{ { 静态代码块 } }
            • 特点

              • 每次创建对象时调用,而且先于构造器调用
            • 作用

              • 为实例变量初始化(赋值),一般是多个构造器中重复的代码提取到构造块
      • 在方法中

        • 局部代码块(了解)
    • 相关的面试题

      • 赋值和执行的顺序

        • 父类的静态代码块 – 》子类的静态代码块 –》父类的构造块–》父类的构造器 –》子类的构造块 –》子类的构造器
      • 关于static的重写问题

        • 静态的方法和属性,没有编译时类型和运行时类型的区别,只有编译时类型,换句话说没有重写(覆盖)一说

          package com.atguigu.static_.buchong;

          /*

          • 静态的方法:不存在编译时和运行时类型,只有编译时类型

          • 静态的属性:不存在编译时和运行时类型,只有编译时类型

          */

          public class Test {

          public static void main(String[] args) {

            SuperClass s = new SubClass();
          
            s.test();//父类的方法
          
            System.out.println(s.info);//尚硅谷
          

            SubClass sub = new SubClass();
          
            sub.test();//子类的方法
          
            System.out.println(sub.info);//atguigu
          

          }

          }

          class SuperClass{

          static String info = “尚硅谷”;

          public static void test(){

            System.out.println("父类的方法");
          

          }

          }

          class SubClass extends SuperClass{

          static String info = “atguigu”;

          public static void test(){

            System.out.println("子类的方法");
          

          }

          }

  • (5)内部类

    • 什么情况下使用内部类

      • (1)当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类 (2)内部类可以访问外部类的所有的成员,包括私有的
    • 形式

      • 成员

        • 静态内部类

          • 格式

            • [修饰符] class 外部类{ [修饰符] static class 内部类{ } }
          • 修饰符的问题

            • (1)权限修饰符

              • 4种
            • (2)static

              • 必须得有
            • (3)final(极少)

              • 可以

                • 表示不能被继承
            • (4)abstract(极少)

              • 可以

                • 表示可以包含抽象方法,需要子类继承
          • 静态内部类的成员

            • 所有都可以,包括静态的
          • 使用问题

            • (1)在静态内部类中使用外部类的成员

              • 只能使用外部类的静态成员
            • (2)在外部类中使用静态内部类

              • 都可以
            • (3)在外部类的外面,其他类中

              • (1)用静态内部类的静态成员

                • 外部类名.内部类名.静态成员
              • (2)用静态内部类的非静态成员

                • 需要静态内部类的对象
                • 外部类名.内部类 变量 = new 外部类名.内部类(); 变量.成员….
        • 非静态内部类,通常称为成员内部类

          • 格式

            • [修饰符] class 外部类{ [修饰符] class 内部类{ } }
          • 修饰符的问题

            • (1)权限修饰符

              • 4种
            • (2)static

              • 没有
            • (3)final(极少)

              • 可以

                • 表示不能被继承
            • (4)abstract(极少)

              • 可以

                • 表示可以包含抽象方法,需要子类继承
          • 非静态内部类的成员

            • 除了静态成员,其他都可以
          • 使用的问题

            • (1)在非静态成员内部类中使用外部类的成员

              • 都可以
            • (2)在外部类中使用非静态成员内部类

              • 在外部类的静态成员中不能使用非静态成员内部类

                • 静态 (不能用) 非静态

                  • 原因,静态的成员先加载,非静态只有创建对象才有
            • (3)在外部类的外面使用非静态成员内部类

              • 依赖于外部类的对象

              • 形式一

                • (1)先创建外部类的对象

                  • 外部类 out = new 外部类();
                • (2)通过外部类的对象创建内部类的对象

                  • 外部类.内部类 in = out.new 内部类();
                • (3)通过内部类对象调用它的成员

                  • in.成员
              • 形式二

                • (1)在外部类中提供一个方法,用来返回内部类的对象

                  • class 外部类{ class 内部类{ }

    public 内部类 getInnerInstance(){ return new 内部类(); }

}

						- (2)创建外部类的对象

							- 外部类  out = new  外部类();

						- (3)通过外部类的对象,获取内部类的对象

							- 外部类.内部类  in = out.getInnerInstance();

						- (4)通过内部类对象调用它的成员

							- in.成员

			- 面试题

				- 如何继承非静态成员的内部类

					- 示例

					  class Outer{

					  	class Inner{

					  	}

					  }

					  class Other extends Outer.Inner{

					  	Other(Outer out){

					  		out.super();

					  	}

					  }

	- 局部

		- 有名字的局部内部类,通常称为局部内部类

			- 格式

				- [修饰符] class 外部类{
[修饰符] 返回值类型  方法名([形参列表]){
	[修饰符] class 内部类{
	}
}

}

			- 修饰符的问题

				- (1)权限修饰符

					- 都不行

				- (2)static

					- 没有

				- (3)final(极少)

					- 可以

						- 表示不能被继承

				- (4)abstract(极少)

					- 可以

						- 表示可以包含抽象方法,需要子类继承

			- 有名字的局部内部类的成员

				- 除了静态成员,其他都可以

			- 使用

				- (1)在内部类中使用外部类的成员

					- 受所在方法的约束,如果所在方法是静态的,那么只能使用外部类的静态成员,如果所在方法是非静态的,那么都可以使用

				- (2)在内部类中使用外部类的局部变量

					- 必须是final修饰

						- JDK1.8之前,必须显式声明
						- JDK1.8之后,默认就是final修饰

				- (3)在外部类中使用内部类

					- 只能在声明它的方法中使用,而且在声明之后使用

						- 和局部变量的作用域一样

				- (4)在外部类的外面

					- 不可以

				- (5)在外部类的其他方法中

					- 不可以

		- 匿名内部类

			- 格式

				- new 父类/父接口(){
方法

}

			- 修饰符

				- 一个都没有

			- 匿名内部类的成员

				- 除了非静态的都可以,但是一般很少自定义方法等成员,它的成员都是重写父类的,父接口的方法

			- 匿名内部类的特点

				- (1)声明类和创建对象同时进行, 只有一个对象

				  	public static void main(String[] args) {

				  		//Object的一个子类对象

				  		new Object(){

				  			public void test(){

				  				System.out.println(this.getClass());

				  			}

				  		}.test();

				  		//Object的另一个子类对象

				  		new Object(){

				  			public void test(){

				  				System.out.println(this.getClass());

				  			}

				  		}.test();

				  	}

				- (2)子类一定会调用父类的构造器

				  class MyClass{

				  	private String info;

				  	MyClass(String info){

				  		this.info = info;

				  	}

				  }

				  		//创建一个MyClass的子类对象,使用匿名内部类

				  		MyClass m = new MyClass("参数"){

				  		};

			- 匿名内部类的使用形式

				- 形式一

					- 匿名内部类的匿名对象直接调用方法

					  		new Object(){

					  			public void test(){

					  				System.out.println(this.getClass());

					  			}

					  		}.test();

				- 形式二

					- 与父类或父接口构成多态引用

					  class MyClass{

					  	public void test(){

					  		System.out.println("父类的测试方法");

					  	}

					  }

					  		MyClass m = new MyClass(){

					  			public void test(){

					  				System.out.println("重写");

					  			}

					  		};

					  		m.test();

				- 形式三

					- 匿名内部类的匿名对象作为实参

					  		MyClass[] arr = new MyClass[5];

					  		Arrays.sort(arr, new Comparator(){

					  			@Override

					  			public int compare(Object o1, Object o2) {

					  				return 0;

					  			}

					  		});

			- 使用其他要求

				- (1)在内部类中使用外部类的成员

					- 受所在方法的约束,如果所在方法是静态的,那么只能使用外部类的静态成员,如果所在方法是非静态的,那么都可以使用

				- (2)在内部类中使用外部类的局部变量

					- 必须是final修饰

						- JDK1.8之前,必须显式声明
						- JDK1.8之后,默认就是final修饰

3.4 (4)类的声明格式

  • 格式

    • [修饰符] class 类名{ //属性列表 //构造器列表 //get/set方法 //其他方法 }

3.5 (5)如何创建对象

  • new 类名()

    • 用无参构造
  • new 类名(实参列表)

    • 用有参构造
  • 匿名对象和有名对象

    • Student stu = new Student();

      • stu对象名,也可以称为对象的引用
    • 匿名对象

      • System.out.println(new Student());
  • 对象的内存图

4 、面向对象的基本特征

4.1 封装

  • 封装的作用

    • 安全

    • 使用方便

      • 对于使用者屏蔽实现细节
  • 概念

    • 狭义

      • 属性的封装

        • (1)属性私有化:private
        • (2)提供公共get/set方法
    • 广义

      • 方法
      • 组件
      • 系统

4.2 继承

  • 什么情况下需要继承?继承的好处是什么?

    • 为了代码重用

      • (1)当有一个父类,如果再声明类时,发现这些类与已经存在的父类有很多相同特征,那么就可以通过继承的方式来简化代码
      • (2)已经很多类,发现这些类有很多共同的特点,那么我们可以把这些共同的特点抽取到一个父类中,以便简化代码
    • 逻辑的角度

      • 表示is-a的关系
  • 如何继承

    • 语法格式: [修饰符] class 子类名 extends 父类名{ }
  • 继承后对几个成员的影响

    • 属性

      • (1)子类继承父类时,一定会继承父类的所有的属性,包括私有的,但是由于私有的关键字private的原因,在子类中无法直接操作它,但是可以通过get/set方式操作它

      • (2)当子类的属性与父类的属性重名时,而且父类的属性没有私有化,如果要访问父类的属性那么通过super.属性进行访问,如果子类中没有通过super.属性访问,那这个属性就表示是子类自己的

        • 面试题

          package com.atguigu.review;

          public class Test {

          public static void main(String[] args) {

            Student stu = new Student();
          
            System.out.println(stu.getInfo());//结果?  年龄:10
          
            System.out.println(stu.getAge());//结果?20   如果子类重写,答案是10
          

          }

          }

          class Person{

          int age = 20;

          public int getAge() {

            return age;
          

          }

          public void setAge(int age) {

            this.age = age;
          

          }

          }

          class Student extends Person{

          int age = 10;

          /*public int getAge(){

            return age;
          

          }*/

          public String getInfo(){

            return "年龄:" + age;
          

          }

          }

    • 方法

      • (1)子类继承父类时,一定会继承父类的所有的方法,包括私有的,但是由于private,在子类中无法直接操作,但是可以间接操作
      • (2)当父类的方法实现不适用于子类时,子类可以对父类的方法的进行重写
    • 构造器

      • (1)子类继承父类时,不会继承父类的构造器

      • (2)子类继承父类时,一定会调用父类的构造器

        • 如果父类有无参构造,那么子类会默认去调用父类的无参构造 如果父类没有无参构造,只有有参构造,那么子类必须在子类构造器中手动调用父类的有参构造
        • 调用父类的无参构造的语句:super(); 调用父类的有参构造的语句:super(实参列表); 而且这两个语句必须在子类的构造器的首行。
  • 继承的原则

    • (1)单继承

      • 在Java中只支持单继承,也就是说一个类只能有一个直接父类 –》一个唯一的亲生父亲
    • (2)多层继承

      • 在Java中父类还可以有父类,而且在子类中会继承父类以及父类的父类的所有的属性与方法 –》代代相传

        • 子类对象在寻找一个方法、属性时,如果本类中找不到,会去直接父类中查找,如果直接父类中也找不到,在往上找,找到为止,一直追溯到java.lang.Object根父类中
        • 通过super.属性和方法时,先从直接父类中查找,如果没有,再往上找,直到找到为止,一直可以到java.lang.Object
    • (3)一个类可以有很多个子类,子类还可以有子类

      • 子孙满堂
      • 开枝散叶

4.3 多态

  • 多态的表现形式

    • (1)方法的重载:同一个类中,功能多种实现形式 方法的重写:父子类中,功能的不同实现形式

    • (2)对象的多态性

      • 编译时类型与运行时的类型不一致,编译时看“左边”,运行时看“右边”, 编译时从“父类”中寻找方法,运行时执行的是“子类”重写过的代码

      • 对象的多态性的前提: (1)继承 (2)方法的重写 (3)多态引用

        • 多态引用

          • Person p = new Student();
        • 本态引用

          • Person p = new Person();
          • Student s = new Student();
  • 多态的应用

    • (1)多态参数
    • (2)多态数组
  • 类型的转换

    • 向上转型

      • 子类的对象赋值给父类的变量
      • 自动完成
    • 向下转型

      • 把父类的变量赋值给子类的变量

      • 强制类型转换

      • 如果想要向下转型成功

        • 父类的变量本身指向的就是该子类的对象
      • 如何避免ClassCastException

        • 在向下转型之前,加判断

          • if(变量 instanceof 子类类型){ 子类类型 temp = (子类类型)变量; }
      • 什么情况下需要向下转型

        • 因为一个对一旦向上转型后,那么就无法访问该子类对象中特有的方法,只能访问父类有的方法
        • 如果需要通过该对象,访问子类的特有的方法等,那么就需要向下转型

5 、关键字

5.1 class

  • 声明类

5.2 new

  • 创建实例,创建对象
  • 在堆中申请一块空间
  • 只要new就创建新的对象
  • new后面一定是构造器

5.3 this

  • 当前对象

    • (1)如果在构造器中,表示正在被创建的那个对象 (2)如果在其他方法中,表示调用该方法的那个对象
  • 使用

    • (1)this.属性

      • 当成员变量(属性名)与局部变量(形参)重名时,使用this.属性进行区别
    • (2)this.方法

      • 表示调用“当前类”的方法
      • 如果子类继承了父类,子类没有重写父类的方法,this.方法也可能是从父类继承的方法
      • 如果子类继承了父类,子类重写父类的方法,this.方法就代表子类重写过的代码
    • (3)this()或this(实参列表)

      • 表示调用本类的其他构造器,而且必须在构造器的首行

5.4 super

  • 父类引用

  • 使用

    • (1)super.属性

      • 当子类的属性与父类的属性重名时,而且父类的属性没有私有化 如果需要调用父类的属性,那么通过super.属性进行区别
    • (2)super.方法

      • 当子类的方法重写了父类的方法时, 如果需要调用父类的被重写的方法,那么通过super.方法进行调用
    • (3)super()或super(实参列表)

      • 当子类需要调用父类的构造器时,通过super()或super(实参列表)进行调用

调用父类的无参构造的语句:super(); 调用父类的有参构造的语句:super(实参列表); 而且这两个语句必须在子类的构造器的首行。

5.5 权限修饰符

  • 三个单词,四种形式: public;公共的,范围:任意位置,可以修饰类、成员 protected:受保护的,范围:本包或子类中,可以修饰成员 缺省:默认的,范围:本包,可以修饰类、成员 private:私有的,范围:本类中,可以修饰成员

5.6 static

  • 静态的

  • 可以修饰成员

  • (1)属性

    • 这个属性就称为类变量,它的值是所有对象共享的,存储在方法区 它的get/set方法也是静态的
  • (2)方法

    • 这个方法就称为类方法,调用它不需要创建对象,直接可以通过”类名.方法“调用
  • (3)代码块

    • 用static修饰的代码块称为静态代码块。 随着类的加载并初始时而执行,而且一个类的静态代码块只执行一次 为静态变量赋值,如果静态变量有显式初始化和静态代码块初始化,它俩属于同级,谁在前谁先执行
  • (4)内部类

5.7 final

  • 最终的

  • 可以修饰

    • (1)类

      • 这个类不能被继承,俗称“太监类”
    • (2)方法

      • 这个方法不能被重写,像“圣旨”
    • (3)变量

      • 成员变量

        • 常量

          • 值不能被修改
        • 必须手动初始化

          • 示例

            package com.atguigu.review;

            public class TestFinal {

            }

            class Human{

            // private static final String country = “中国”;

            private static final String country;

            static{

              country = "中国";
            

            }

            }

            class Person{

            // final String country = “中国”;

            private final String country;

            private String name;

            /* {

              country = "中国";
            

            }*/

            Person(){

              country = "中国";
            

            }

            public Person(String name) {

              super();
            
              country = "中国";
            
              this.name = name;
            

            }

            }

      • 局部变量

        • 常量

          • 值不能被修改
        • 必须手动初始化

5.8 native

  • 原生的

  • 可以修饰

    • 方法

      • (1)表示这个方法的方法体是非Java语言实现
      • (2)对于使用这个方法者来说,和普通的Java 方法一样使用
      • (3)如果有需要,也可以进行重写

6 、包

6.1 包的作用

  • (1)避免类的重名 (2)访问权限的控制 (3)便于管理

6.2 如何声明包

  • package 包;

  • 要求

    • 必须在源文件的首行,一个源文件只能有一句
    • 遵循命名规范,所有字母都小写,单词之间使用.,一般以公司的域名倒置

6.3 如何使用其他包的类

  • 需要import 包.类名;

  • 要求

    • 在package和class声明之间,可以多句
    • 被使用的类必须是public 或 protected(父子类)
  • 形式

    • 一一列举

      • import java.util.Random; import java.util.Scanner;
    • 某个包的类

      • import java.util.*;
    • 静态导入

      • import static java.lang.Math.*;
      • System.out.println(PI); System.out.println(sqrt(4));

7 Overload和Override的区别

7.1 Overload:方法的重载

在同一类,方法名称相同,形参列表不同的两个或多个方法称为重载。

Override:方法的重写 在子类继承父类时,如果父类的方法实现不适用于子类,子类就可以对父类的方法进行重写,覆盖。