zoukankan      html  css  js  c++  java
  • Java(1):面向对象

    Java复习笔记(一):面向对象

    0、怎么理解“万事万物皆对象”

    1、在Java语言的范畴内,我们将功能封装到类中,通过类的实例化,来调用具体的功能。

    2、Java与前端交互时,将HTML中的标签转换为对象

    3、Java与后端交互时,将数据库中的表转换为对象

    0、前言:

    • 学习Java面向对象的三条主线
      • 类和类的成员:属性、方法构、构造器、代码块、内部类
      • 面向对象三大特征:封装、继承、多态
      • 其他关键字:this、super、package、import、static、final、abstract、interface

    1、类和类的成员

    1.0、类和对象

    1. 理解
      1. 正如生物由不同功能的细胞构成,Java代码由不同功能的类组成。类的作用正是为我们提供各种的功能。
    2. 语法
    修饰符 class 类名{
        属性声明;
        方法声明;
    }
    
    • 说明:
      • 类的修饰符只有两种:public、缺省
      • 类名:首字母大写
    1. 类的使用
      1. 设计类
      2. 类的实例化
      3. 类的访问机制:
        1. 在同一类中,类的方法可以直接访问类的属性(static的方法只能访问static的属性方法)
        2. 在不同的类中
          1. 对于 非static的:“对象.属性/方法”来使用;
          2. static的方法:“类名.方法”
    2. 对象的使用
      1. 对于类中非static的属性,每个对象都有自己独立的一套属性值

      2. 对象的赋值,是直接把地址值给新对象,不new就不会在内存中开辟空间

      3. 创建对象的内存解析

        1. Stack(栈,通常指虚拟机栈):存储局部变量
          1. 方法体内的变量都是局部变量包括
          2. 基本数据类型
          3. 对象的引用(这里指的是对象再heap中的首地址)
          4. 说明:main方法中的变量也是局部变量,因为main()也是一个方法
        2. Heap(堆):存放对象实例(new的对象、数组等)
        3. 引用数据类型只能存放两种数据:null和地址值
      4. 对象数组的内存解析

    3. 匿名对象
      1. 语法

        new Person().eat();
        
      2. 使用场景

        1. 一个对象只需要一次方法调用时,可以使用匿名对象
        2. 作为实参传递给一个方法时,可以使用匿名对象(实质是把地址值传递给形参)
      3. 注意:每一个new都是不同的对象

    1.1、属性

    1. 说明
      1. 属性,也叫成员变量(成员是相对于类而言的,属性是类的成员),英文field
    2. 语法
      修饰符 数据类型 属性名 = 初始化值;
      
    • 权限修饰符:private、缺省、protected、public

      权限修饰符 访问权限
      public 同一工程
      protected 不同包的子类
      缺省 同一个包
      private 类内部
    • 其他修饰符:static、final

    1. 变量的分类
    成员变量(成员指的是类的成员) 局部变量(局部指的所在的位置比类中还小一级)
    声明的位置 类内,方法体外 方法的形参、方法的内部、代码块内、构造器内
    修饰符 四种权限修饰符+static、final 不使用权限修饰符,可以用final
    初始化值 有默认的初始化值 没有默认的初始化值,必须显式的赋值
    形参在调用时再赋值
    内存加载位置 堆空间 或 静态域 栈空间
    • 成员变量又分为
      • 实例变量:不用static修饰,随着对象的创建而加载,每个对象有自己的一套。
      • 类变量:static修饰,是随着类的加载二加载,多用对象共用一套。
    1. 属性的默认初始化值
    成员变量类型 初始值
    byte 0
    short 0
    int 0
    long 0L
    float 0.0F
    double 0.0
    char 0或'u0000'(表现为空)
    boolean false
    引用类型 null
    1. 属性初始化的顺序

    1.2、方法

    1、说明
    • 方法,也叫成员方法,英文method
    2、语法
    权限修饰符 [static、final] 返回值类型 方法名(形参列表){
        方法体;
        return 返回值;
    }
    
    • 权限修饰符:四种

    • return的说明

      • 作用:结束方法、或、结束方法,并返回某个值
      • 注意:一旦return执行,后面的语句就不会被执行了
    3、类的分类
    1. 公共类 外 测试类 、main
    2. 公共类 里
    4、方法的重载
    • 概念:同一类中,存在一个以上的同名的方法,但是他们的参数类型和参数个数不同
    5、可变个数的形参
    1. 概念:允许直接定义能和多个实参相匹配的形参
    2. 格式:方法名(参数类型名...参数名)
    3. 实质:相当于数组,使用方法和数组下标一样,也因此形参中String[] books和String...books是不能共存的
    4. 应用场景:
      1. 数据库中,where后面不确定有多少个筛选条件
    6、方法参数的值传递机制★★★★★
    1. 概念

      1. 形参:方法声明时的参数
      2. 形参:方法调用时实际传递给形参的参数
    2. Java实参怎么传递给形参呢?---只有一种,就是值传递机制(就是把实际参数的副本传递给方法,参数本身不受影响)

      1. 形参是基本数据类型:把实参的“数据值”传递给形参
      2. 形参是引用数据类型:把实参的“地址值”传递给形参
    3. 画内存解析图解题★★★★★

      1. 例题一:基本数据类型的参数传递

        public class eg1 {
        	public static void main(String[] args) {
        		int x = 5;
        		System.out.println("修改前x= " + x);
        		change(x);
        		System.out.println("修改后x= " + x);
        	}
        	
        	public static void change(int x) {
        		System.out.println("change修改前x= " + x);
        		x = 3;
        		System.out.println("change修改后x= " + x);
        	}
        }
        
        /*
        修改前x= 5
        change修改前x= 5
        change修改后x= 3
        修改后x= 5
        
        说明:change方法只是得到了x的值5,而不是得到了x
        */
        
      2. 例题二:引用数据类型的参数传递

        public class eg2 {
        	public static void main(String[] args) {
        		Person p = new Person();
        		p.age = 5;
        		System.out.println("修改前age= " + p.age);
        		change(p);
        		System.out.println("修改后age= " + p.age);
        	}
        	
        	public static void change(Person p) {
        		System.out.println("change修改前age= " + p.age);
        		p.age = 3;
        		System.out.println("change修改后age= " + p.age);
        	}
        }
        
        class Person{
        	int age;
        }
        
        /*
        修改前age= 5
        change修改前age= 5
        change修改后age= 3
        修改后age= 3
        
        说明:change方法得到了p的地址值,也指向了heap中的p,因此实际修改了age
        
        结论:要想修改、交换,就要传递引用类型变量
        */
        
    7、方法的递归
    1. 递归,构成了隐式的循环
    2. 使用场景和例题
      1. 计算1到100自然数的和
      2. 求n!
      3. 台阶问题
      4. 汉诺塔
      5. 快排

    1.3、构造器

    1. 作用

      1. 创建对象(无参)
      2. 创建对象并初始化(带参)
    2. 语法

      权限修饰符 类名(参数列表){
          
      }
      //权限和类保持一致
      
    3. 注意

      1. 每个类都至少有一个构造器
      2. 一旦显示定义了构造器,系统就不再提供默认构造器
      3. 可以创建多个重载的构造器
      4. 子类不能继承父类的构造器

    1.4、代码块

    1. 作用:对类或对象进行初始化

    2. 分类:

      1. 静态代码块(用static修饰)

        1. 内部可以有输出语句
        2. 随着类的加载而执行,只执行一次
      2. 非静态代码块

        1. 内部可以有输出语句
        2. 每次创建对象,都会执行一次
      3. 两者特点和对比

        静态代码块 非静态代码块
        可以有输出语句 可以有输出语句
        可以对类的属性,类的声明做初始化 可以对类的属性,类的声明做初始化
        不能调用非静态的 静态非静态都可以调用
        优先于非静态代码块执行
        随着类的加载而加载,且只执行一次 每创建一个对象,就执行一次,优先于构造器
      4. 顺序:静态代码块>非静态代码块>构造器

    3. 使用:开发中的使用一般是为了初始化,但是用的较少。源码中出现要看懂

    1.5、内部类

    1.6、属性赋值的顺序

    ①默认初始化

    ②显示初始化==代码块初始化

    ③构造器初始化

    ④通过对象.属性/方法的形式赋值

    • 后执行的会覆盖先执行的操作

    1.7、JavaBean

    1. JavaBean是java语言写成的可重用组件
    2. JavaBean是一个,要符合下列特征
      1. 类是公共的
      2. 有一个无参的公共的构造器
      3. 有属性和对象的get、set方法

    1.8、UML类图

    2、面向对象三大特征

    2.1、封装

    1. 封装的引入
    • 使用者如果可以直接操作类内部定义的属性,会导致:数据错误混乱、安全性问题--->把属性声明为private,再体统public的get、set方法实现对属性的操作。
    • 当然,private还可以用在方法(仅在类的内部使用这个方法)和构造器(单例模式)中。

    2.2、继承

    1、继承的引入
    1. 多个类中具有相同的属性和行为,把这些内容抽取到单独的一个类中,其他的类只需要继承这个类,就能得到这些属性和行为。
    2. 语法:class Subclass extends Supclass{}
    3. java只支持单继承
    2、重写(override/overwrite)
    1. 重写后的方法会覆盖父类中的方法,也因此,子类更具体、更强大
    2. 重写的要求
      1. 两同一不同:方法名相同、参数列表相同;方法体不同
      2. 重写的方法返回值小于等于被重写的
      3. 重写的方法访问权限大于等于被重写的
      4. 子类不能重写父类中private的方法(不可见)
      5. 子类重写方法抛出的异常小于等于父类被重写的方法的异常

    2.3、多态

    1、多态性的体现
    • 父类的引用指向子类的对象// 子类的对象赋给父类的引用// Person p = new Man()
    2、多态的应用
    1. 方法形参要的是父类类型,我们可以传递给他子类的对象
    3、虚拟方法调用★★★★★
    1. 含义:子类重写了父类的方法,多态情况下,父类的方法就叫 虚拟方法。父类根据赋给他的 不同子类的对象,动态的调用属于子类的该方法。这样的方法调用在编译器是无法确定的,因此称为动态绑定
    2. 用法
      1. 编译时,只能调用引用类型的变量中(即父类中)有的方法
      2. 运行时,调用实际new的对象的类中重写的方法
    3. 应用示例:连接数据库时
    4、instanceof
    1. 引入:有了多态以后,内存中有了子类的属性和方法,但是我们声明的父类类型,因此调用不了子类特有的属性和方法。怎么调用子类特有的属性方法呢---->强制类型转换为子类类型再调用,这时就要判断是不是这种类型,再进行转换。

    2. 自动类型提升(从子类到父类,自动进行)和强制类型转换(从父类到子类,instanceof判断再进行)

    3. 区分

      1. 对于属性来说,编译和运行都看左边。(也就是说,属性不会被继承锁覆盖,无论如何都是自己的属性)

      2. 对于方法来说,编译看左边(只调用父类的方法保证编译器不报错),运行看右边(实际执行的是new的对象的类的方法)。

      3. 怎么证明多态是运行时行为★★★★★

        class Animal  {
         
        	protected void eat() {
        		System.out.println("animal eat food");
        	}
        }
        
        class Cat  extends Animal  {
         
        	protected void eat() {
        		System.out.println("cat eat fish");
        	}
        }
        
        class Dog  extends Animal  {
         
        	public void eat() {
        		System.out.println("Dog eat bone");
        	}
        }
        
        class Sheep  extends Animal  {
        	public void eat() {
        		System.out.println("Sheep eat grass");
        	}
        }
        
        public class InterviewTest {
        
        	public static Animal  getInstance(int key) {
        		switch (key) {
        		case 0:
        			return new Cat ();
        		case 1:
        			return new Dog ();
        		default:
        			return new Sheep ();
        		}
        	}
        
        	public static void main(String[] args) {
        		int key = new Random().nextInt(3);
        
        		System.out.println(key);
        
        		Animal  animal = getInstance(key);
        		
        		animal.eat();	 
        	}
        }
        
      4. 多态笔试题

        public class InterviewTest1 {
        
        	public static void main(String[] args) {
        		Base1 base = new Sub1();
        		base.add(1, 2, 3);
        
        		Sub1 s = (Sub1)base;
        		s.add(1,2,3);
        	}
        }
        
        class Base1 {
        	public void add(int a, int... arr) {
        		System.out.println("base1");
        	}
        }
        
        class Sub1 extends Base1 {
        
        	public void add(int a, int[] arr) {//从实质上看,算是重写,编译器也这么认为
        		System.out.println("sub_1");
        	}
        
        	public void add(int a, int b, int c) {//优先使用确定参数的方法
        		System.out.println("sub_2");
        	}
        }
        
    5、例题

    3、其他关键字

    3.1、this

    1. 含义:表示当前对象
    2. 调用谁:this可以调用属性、方法、构造器
    3. 在哪里调用
      1. 在方法或构造器内,如果使用当前类的成员变量或成员方法,可以在其前面加this。但通常省略。
      2. 当形参和成员变量同名,在成员变量前加this以示区分
      3. 用this来访问属性和方法时,本类中没有,就会去父类中找
      4. 在构造器中调用时的几点说明
        1. 构造器中可以用 this(形参列表),调用本类中其他重载的构造器
        2. 不能调用自身、不能成环、n个构造器最低多有n-1个用this(形参列表)

    3.2、super

    1. 含义:父类中的
    2. 调用谁:super可以调用属性、方法构、造器
    3. this和super的对比:this是调用的本类中的,二super是调用父类中的

    3.3、package

    1. 引入:包主要用来对类和接口进行分类。当开发 Java 程序时,可能编写成百上千的类,因此很有必要对类和接口进行分类。

    2. 格式:package 顶级报名.子包名;,分别对应目录的层次

    3. 位置:第一行

    4. 了解一下JDK中主要的包

      说明
      java.lang 包含一些java的核心类:String、Math、Integer、System、Thread,提供常用功能
      java.net 包含执行和网络相关的操作的类和接口
      java.io 包含能够提供多种输入输出功能的类
      java.util 实用工具类
      java.text java格式相关的类
      java.sql java进行JDBC数据库编程的相关类和接口
      java.awt 构成抽象窗口工具集(abstract 、window、toolkits)的多个类,用来构建和管理GUI

    3.4、import

    1. 引入:在 Java 中,如果给出一个完整的限定名,包括包名、类名,那么 Java 编译器就可以很容易地定位到源代码或者类。import 语句就是用来提供一个合理的路径,使得编译器可以找到某个类

    2. 使用说明

      1. java.util.*----一次导入util下的所以类和接口

      2. 如果导入的类或接口是java.lang包下,或当前包下,可以省略导包

      3. 代码中包含不同包下的同名类,需要用全类名

      4. 如果已经导入导入了java.a包下的类,如果要使用a包的子包中的类,还是要导包

      5. import static组合使用:调用指定类或接口下的静态的属性和方法

        import static java.lang.System.*
        out.println("hello");
        
        等价于:System.out.println();
        

    3.5、static

    1. static的引入
      1. 当我们希望:不管是否产生对象,不管有多少对象,某些特定的数据在内存中只有一份。
      2. 这时,我们就可以引入static关键字
      3. static关键字可以修饰:属性、方法、代码块、内部类
      4. 修饰后的成员的特点:
        1. 随着类的加载而加载,因此:①类只加载一次,静态变量也加载一次,加载在方法区的静态域中②优先于对象存在③可以不创建对象,而直接用类来调用
        2. 被所以对象共享
    2. static修饰属性
      1. static修饰属性---->多个对象共享这个静态变量,如果一个对象修改了这个静态变量,后续的对象再调用,就是修改过后的。

      2. 实例变量和静态变量

        变量类型 特点
        实例变量 每个对象都有独立的一套属性
        静态变量 公用一个静态变量
    3. static修饰方法
      1. 可以不创建对象直接用类调用方法
      2. static修饰的方法不能被重写
    4. 应用场景
      1. static属性

        1. 不会随着对象的变化而变化的属性,可以声明为static的
        2. 具体的场景有:自动赋值、自动生成等字眼(这时就可在构造器加入:静态变量++注:每个构造器都要加)
      2. static类

        1. 操作静态属性的方法,通常是静态方法
        2. 工具类中的方法,习惯上声明为static的(Math、Arrays、Collections)
      3. 单例模式(面试题):某个类只存在一个对象实例

        1. 饿汉式

          class Singleton(){
              //1.外部不能创建---私有化类的构造器
              private Singleton(){}
              //2.内部帮你创建---内部提供当前类的实例
              private static Singleton single = new Singleton();
              //3.给外部提供得到的方法---提供公共的静态方法,返回当前类的对象
              public static Singleton getInstance(){
                  return single;//4.这里用到了single,所以必须是静态的,回去改正
              }
          }
          
        2. 懒汉式

          class Singleton(){
              //1.外部不能创建---私有化类的构造器
              private Singleton(){}
              //2.内部帮你创建---内部提供当前类的实例
              private static Singleton single;
              //3.给外部提供得到的方法---提供公共的静态方法,返回当前类的对象
              public static Singleton getInstance(){//4.这里用到了single,所以必须是静态的,回去改正
                  if(single == null){
                      single = new Singleton;
                  }
                  return single;
              }
          }
          
        3. 两者对比

          饿汉式 懒汉式
          好处 线程安全 延迟创建对象
          坏处 对象加载的时间过长 目前的写法线程不安全(多线程时修改)
        4. 使用场景

          1. 网站计数器、数据库连接池、任务管理器、回收站

    3.6、final

    1. final类
      1. 不能被继承(绝后。。。)
      2. 举例:String类、System类、StringBuffer类
      3. 为什么要声明为final:因为系统把该有的功能都提供了,不用我们自己搞新花样啦!
    2. final方法
      1. 不能被重写(自己写方法一般不加final)
      2. 举例:Object类中的getClass()
      3. 为什么:只让我们用这个方法做这一件事
    3. final
      1. final+变量==常量
        1. 修饰属性(成员变量):必须显式赋值/代码块中赋值/每个构造器中都初始化
        2. 修饰局部变量:使用final修饰形参时,表示形参是常量,调用方法时赋常量给形参,只能在方法体内使用,而且不能再修改
      2. 举例:PI
      3. 为什么:不能修改这个数,也没必要改
    4. static final一起使用
      1. 修饰属性:全局常量(接口中的属性都是这样的)
      2. 修饰方法:很少用到

    3.7、abstract★★★★★

    1. 引入:随着继承层析的增加,子类越来越具体,父类越来越一般、通用、抽象。有时一个父类特别抽象,以至于没有具体的实例,这样的类就叫抽象类。抽象类就像作文模板,我们只需要在可变的部分修修补补就好了。

    2. abstract修饰类

      1. 抽象类不能实例化。因此,我们都要提供他的子类,让子类实例化(否则抽象类有意义)。
      2. 抽象类中仍然有构造器。便于子类实例化的时候使用
      3. 包含抽象方法的类,一定是抽象类(因为有了抽象方法,就要保证这个抽象方法不能被调用)。反之,抽象类里可以没有抽象方法。
    3. abstract修饰方法

      1. 格式:加abstract关键字,没有方法体,并且分号结尾
      2. 子类重写了所有父类中的所有抽象方法,才可以实例化。否则,还是抽象类,要加abstract。
    4. 应用场景举例

      1. 计算计划人图形的面积(因为不知道是具体什么图形,计算方法就不一样)
    5. 注意

      1. abstract不能修饰私有方法:因为子类不可见
      2. abstract不能修饰静态方法
      3. abstract不能修饰final的类或方法
    6. 抽象类的匿名子类(只用一次,图省事)(见到要认识)

      //Person类是抽象的
      
      //创建匿名子类的对象
      Person p = new Person(){//并不是new的Person的对象,而是子类的对象
          @Override
          public void eat(){
              
          }
      }
      
      //创建匿名子类的匿名对象
      method(new Person(){
          @Override
          public void eat(){
              
          }
      })
      

    3.8、interface★★★★★

    1. 引入:Java不支持多继承,但是我们需要这个功能,所以用接口interface来实现多重继承的效果

    2. 接口的本质:标准、规范。接口是抽象方法全局常量的集合

    3. 接口的特点

      1. 和类是并列的关系
      2. 接口中的成员变量默认public static final修饰的,即使省略了,也还是存在。因此接口中的成员变量是全局常量
      3. 接口中的方法默认public abstract修饰的,即使省略了,也还是存在。因此接口中的方法是抽象方法
      4. 接口中没有构造器,因此不能实例化。只能通过类实现接口实现所有的抽象方法,在实例化
    4. 接口和抽象类的对比(面试题)

    3.9、main()的使用说明

  • 相关阅读:
    ansible使用
    git undo last commit
    metadata简介
    tinyint(4),tinyint(80)有什么区别
    php 打印debug日志
    tinycore Network card configuration during exec bootlocal.sh
    Windows使用CMD命令查看进程和终止进程
    @NotEmpty,@NotNull和@NotBlank的区别
    spring boot 程序启动缓慢的问题(二)
    LocalDateTime的一些用法
  • 原文地址:https://www.cnblogs.com/liuzhixian666/p/13904934.html
Copyright © 2011-2022 走看看