JAVA SE 3.面相对象

1.类和对象的定义

  • 1.:指对现实中对象的共性抽取,通常用来表示同一批具有相同特征和行为的对象
  • 2.对象:指类的实例化,其是计算机内存中的一块存储空间,用来存储现实中对象特性和行为的描述
  • 3.类和对象的关系
    • 1.类是对象的模板
    • 2.对象是类的实例

2.类

  • 1.属性:用来描述对象的特征
    局部变量 成员变量(属性)
    位置 形参或方法、代码块内部 类的内部、方法的外部
    默认值 没有
    作用范围 从定义开始到定义的{}结束 当前整个类
    命名冲突 局部变量之间不能重名 属性可以和局部重名,局部变量优先更高
  • 2.方法:用来描述对象行为
    方法修饰符 返回值类型 方法名(参数列表){
          
    	// 操作语句
    }
    
  • 3.规则:
    • 1.一个源文件中只能有一个public
    • 2.一个源文件可以有多个非public
    • 3.源文件的名称应该和public类的类名保持一致
    • 4.如果一个类定义在某个包中,那么package语句应该在源文件的首行
    • 5.如果源文件包含import语句,那么应该放在package 语句和类定义之间;如果没有package语句,那么import语句应该在源文件中最前面
    • 6.import语句和package语句对源文件中定义的所有类都有效;同一源文件中不能给不同的类不同的包声明

1.属性

类变量 实例变量
修饰符 static关键字
访问方式 类或类对象 类的对象
生存周期 静态成员不依赖于类的特定实例,被类的所有实例共享;static 修饰的方法或者变量不需要依赖于对象来进行访问,只要这个类被加载,Java 虚拟机就可以根据类名找到它们 与对象同存亡,被对象调用后才分配内存,调用结束时内存释放
加载时机 运行时Java 虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配 每创建一个实例,Java 虚拟机就会为实例变量分配一次内存
  • 1.类的属性分为(具体可参考基本语法中的变量的作用域
    • 1.类变量/静态变量(static修饰)
    • 2.实例变量

2.方法

  • 1.构造方法
  • 2.静态方法
  • 3.普通方法

1.方法重载

  • 1.定义
    • 1.方法重载:指在同一个类中定义多个方法,它们具有相同的名称但参数列表不同,根据不同的传参来执行不同的逻辑处理
  • 2.规则
    • 1.重载的方法必须具有相同的方法名
    • 2.参数列表必须不同(参数类型,个数,顺序)
    • 2.访问修饰符返回类型异常不影响方法重载
      在这里插入图片描述

2.方法重写

  • 1.定义
    • 1.方法重写:指子类重新定义父类中已有的方法,以实现特定的功能
    • 2.当子类对父类方法进行重写之后,子类对象调用方法执行的是子类重写的内容
  • 2.规则
    • 1.必须存在于继承关系中
    • 2.重写的方法必须与父类方法具有相同的方法名
    • 3.参数的类型、个数和顺序必须相同
    • 4.返回类型必须与父类方法相同或是其子类
    • 5.子类方法的访问修饰符不能比父类方法更严格(如父类方法是protected,子类方法可以是 public,但不能是 private
    • 6.子类不允许抛出比父类范围更大的异常
    • 7.私有方法,构造方法,静态方法无法被重写
      • 1.静态方法属于类,不属于实例,重写是针对实例方法而静态方法不是实例方法,因此不能重写;其次静态方法在编译时绑定到类,而不是在运行时绑定到实例,重写依赖于动态绑定,因此不能重写;静态方法通过类名调用,而不是通过实例调用,即使子类定义了与父类相同的静态方法,调用时仍然是根据引用类型决定调用哪个方法,而不是根据实际对象类型
      • 2.私有方法的访问权限决定了其只能在定义的类内部访问,子类无法访问父类的私有方法,因此也无法重写它
      • 3.构造方法是用于对象初始化的特殊方法不属于类的实例方法,重写是针对实例方法,而构造方法不是实例方法,因此不能重写;构造方法在创建对象时由JVM自动调用,子类的构造方法必须显式或隐式地调用父类的构造方法,如果允许重写构造方法,子类可能会绕过父类的初始化逻辑,导致对象状态不一致;构造方法的名称必须与类名相同,而重写要求方法名相同,子类的类名与父类的类名不同,因此无法满足重写的条件
  • 3.方法重写与重载的区别
    >
|区别点|重载方法|重写方法|
|--|--|--|
|发生范围|同一个类|子类中|
|参数列表|必须修改|一定不能修改|
|返回类型|可修改|可以相同或其子类|
|异常|可修改|可以减少或删除,一定不能抛出新的或者更广的异常|
|访问修饰符|可修改|一定不能做更严格的限制(可以降低限制)|
|发生阶段|编译期|运行期|

3.this()方法

  • 1.用于在当前类的构造方法中调用另一个构造方法
  • 2.只能写在构造方法有效代码第一行
  • 3.由this()实参列表决定调用哪个构造方法
  • 4.构造方法无法通过this()调用自身,这样会成为死循环调用从而导致内存溢出
  • 5.构造方法之间也不能相互循环调用,否则会死循环从而导致内存溢出
  • 6.应用场景
    • 1.构造方法重载:通过 this() 调用当前类的其他构造方法,避免代码重复
    • 2.初始化逻辑复用:将通用的初始化逻辑放在一个构造方法中,其他构造方法通过 this() 调用

4.super()方法

  • 1.用于在子类的构造方法中调用父类的构造方法
  • 2.只能写在子类构造方法有效代码第一行
  • 3.由super()实参列表决定调用哪个父类构造方法
  • 4.this()super()不能同时出现(因为this()super() 必须作为构造方法的第一条语句)
  • 5.如果子类构造方法没有显式调用父类构造,那么无参的super()默认存在于子类构造方法第一行(编译器自动插入)
  • 6.当子类构造显式调用this()时,当前构造方法就只能使用默认的无参super()
  • 7.如果父类没有无参构造方法,子类必须显式调用父类的有参构造方法
  • 8.应用场景
    • 1.初始化父类状态:确保父类的状态被正确初始化
    • 2.调用父类构造方法:在子类构造方法中显式调用父类的构造方法
      在这里插入图片描述

5.构造方法

  • 1.定义:构造方法是一种特殊的方法,用于在创建对象时初始化对象的状态
  • 2.构造方法的访问修饰符只能使用public,且构造方法名和类名必须一致
  • 3.没有返回类型(包括 void
  • 4.使用new关键字来调用构造方法
  • 5.当类中没有提供显式构造方法,默认提供一个无参数的构造方法
  • 6.当类中提供了显式构造方法,将不再默认提供无参数构造方法
  • 7.建议将无参数构造方法显示声明,这样一定不会出问题
  • 8.构造方法支持方法重载,不支持方法重写
  • 9.子类构造方法必须调用父类的构造方法(显式或隐式)

6.静态方法和普通方法

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

  • 1.定义: 使用static修饰的方法称为静态方法,静态方法属于类,而不是类的实例
  • 2.生命周期:静态方法在类加载时分配内存(方法区),程序结束时释放内存,所有实例共享同一个静态方法;普通方法在对象创建时分配内存(方法区),对象销毁时释放内存,每个实例都有自己的普通方法调用栈,通方法的调用依赖于实例,因此需要通过实例来访问
  • 3.作用范围:静态方法只能访问静态数据(静态变量和静态方法),非静态方法既可以访问静态数据又可以访问非静态数据
  • 4.因为静态方法静态数据会随着类加载而被加载到内存中,而非静态方法非静态数据只有在对象创建时才会加载到内存中,如果静态方法调用了了非静态数据,则在静态方法加载时无法从内存中找到非静态数据,势必会出错,这种做法是Java虚拟机不允许的
  • 5.调用方式:引用静态方法时,可以用类名.方法名或者对象名.方法名的形式
  • 6.静态方法中不能使用thissuper关键字,因为这两个关键字都依赖于对象

7.代码块和静态代码块

class 类名{
    
	static{
    
		// 静态初始代码块
	}
	{
    
		// 普通代码块
	}
}
  • 1.定义:static修饰的代码块称为静态代码块
  • 2.静态代码块只有在类加载时才会执行,且只执行一次,一个静态代码块没有执行完成时不会执行下一个静态代码块,静态代码块属于类,而不是实例
  • 3.普通代码块在创建对象时执行,每次创建对象时都会执行,且在构造方法之前执行,代码块属于实例
  • 4.执行顺序静态代码块 > 普通代码块 > 构造函数
  • 5.静态代码块只能访问类中的静态成员变量
  • 6.普通代码块只能访问类中的成员变量
  • 7.位置:两者一般都写在属性之下,方法之上,静态代码块类似于一个方法,但它不可以存在于任何方法体中,静态代码块可以置于类中的任何地方,类中可以有多个静态初始化块
  • 8.作用:静态代码块一般是为了给静态成员变量赋值,一般将一些只需要进行一次的初始化操作都放在静态代码块中进行;代码块一般是为了给成员变量赋值
  • 9.如果类中包含多个静态代码块,则Java虚拟机将按它们在类中出现的顺序依次执行它们,每个静态代码块只会被执行一次
  • 10.静态代码块与静态方法一样,不能直接访问类的实例变量和实例方法,而需要通过类的实例对象来访问,静态代码块和普通代码块的字节码都存储在方法区
  • 11.代码块的应用场景
    • 1.初始化实例变量:代码块在构造方法之前执行,用于初始化实例变量
    • 2.复用初始化逻辑:多个构造方法共享相同的初始化逻辑
  • 12.静态代码块的应用场景
    • 1.初始化静态变量:在类加载时执行,用于初始化静态变量。
    • 2.加载静态资源:在类加载时加载静态资源(如配置文件、数据库连接等)

8.方法返回值

  • 1.指获取到的某个方法体中的代码执行后产生的结果
  • 2.返回值的作用是接收结果,使得其可以用于其他的操作
  • 3.方法返回值可以是基本数据类型,也可以是引用数据类型void表示方法没有返回值

3.类加载机制

  • 1.参考JVM及GC文章中的类加载子系统

3.抽象类

在这里插入图片描述

  • 1.用abstract修饰的类
  • 2.抽象类不能实例化对象,设计理念是为了服务其他子类,所以规定不能实例化
  • 3.其它功能和普通类一致
    • 1.可以有构造方法,用于初始化成员变量
    • 2.可以有成员变量:抽象类可以定义成员变量
    • 3.可以有具体方法:抽象类可以定义具体方法(有实现的方法)
    • 4.可以有静态方法:抽象类可以定义静态方法
  • 4.由于抽象类不能实例化对象,所以抽象类必须被继承才能被使用
  • 5.Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口
  • 6.privatestaticfinal不能与abstract连用,因为abstract需要被继承实现且无法被实例化
    • 1.如果 staticabstract 连用,会导致语义矛盾:static 方法可以直接调用,但 abstract 方法没有实现,无法调用
    • 2.static 方法的调用不依赖于实例,而 abstract 方法的实现依赖于子类,如果允许 staticabstract 连用,会导致调用 static 方法时无法确定具体的实现
  • 7.应用场景
    • 1.定义通用行为:抽象类可以定义一组通用的行为(具体方法),子类可以直接继承这些行为
    • 2.强制子类实现特定行为:抽象类可以定义抽象方法,强制子类实现特定的行为
    • 3.代码复用:抽象类可以将通用的代码放在具体方法中,子类可以直接复用这些代码
      在这里插入图片描述

1.抽象方法

  • 1.用abstract修饰的方法
  • 2.抽象类中的抽象方法只有声明,没有方法体
  • 3.抽象方法具体实现由它的子类实现
  • 4.抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类
  • 5.任何子类必须重写父类的抽象方法,除非子类也是抽象
  • 6.最终必须有子类实现该抽象方法,否则从最初的父类到最终的子类都不能用来实例化对象
  • 7.私有方法,构造方法,静态方法(用 static 修饰的方法)不能声明为抽象方法
    • 1.语义矛盾:构造方法用于初始化对象,而抽象方法没有实现,无法完成初始化,如果构造方法是抽象的,子类无法调用父类的构造方法,导致对象无法正确初始化
    • 2.设计原则:构造方法必须在对象创建时执行,而抽象方法需要在子类中实现,这两者是矛盾的
      在这里插入图片描述

4.内部类

  • 1.定义:内部类是定义在另一个类内部的类
  • 2.根据定义位置和修饰符不同,内部类可分为
    • 1.成员内部类
    • 2.静态内部类
    • 3.局部内部类
    • 4.匿名内部类
  • 3.内部类的优缺点
    • 1.优点:可实现回调接口、封装隐藏实现细节、简化代码结构和实现类似多继承的效果
    • 2.缺点:可能会增加代码的复杂性,如果滥用内部类,可能会导致代码难以理解和维护
  • 4.内部类的生命周期
    • 1.成员内部类的生命周期依赖于外部类的生命周期
    • 2.静态内部类的生命周期独立于外部类的生命周期
    • 3.局部内部类的生命周期仅限于定义它的方法或构造器的执行过程
    • 4.匿名内部类的生命周期依赖于它的父类或接口的生命周期
  • 5.内部类是否有静态成员
    • 1.成员内部类和匿名内部类不能有静态成员,因为它们依赖于外部类的实例
    • 2.局部内部类不能有静态成员,因为其生命周期仅限于定义它的方法或构造器
    • 3.静态内部类可以有静态成员,因为它独立于外部类的实例
  • 6.应用场景
    • 1.实现回调接口:事件处理中使用内部类来实现事件监听器接口,当事件发生时内部类的方法会被调用,从而实现回调
    • 2.封装隐藏实现细节:内部类可以隐藏实现细节,只对外暴露必要的接口,这样可以提高代码的封装性和安全性,如将一些辅助类或工具类定义为内部类,只在外部类中使用,而对外部隐藏这些类的实现细节

1.成员内部类

class 外部类名{
    
	class 内部类类名{
    

	}
}
class Outer {
    
   private int outerVar = 10;
   class Inner {
    
       void display() {
    
           System.out.println("OuterVar: " + outerVar);
       }
   }
}
  • 1.定义:类的内部,方法的外部,与属性和方法平级
  • 2.成员内部类可以访问外部类的所有成员属性成员方法(包括private成员和静态成员)
  • 3.成员内部类不能定义静态内容,但是可以访问外部类静态内容(由于成员内部类的实例化依赖于外部类的实例,因此在内部类中定义静态成员会导致语义上的冲突,静态成员属于类级别,不依赖实例,因此成员内部类可以直接访问)
  • 4.如果外部类属性,内部类属性,内部类局部变量出现重名
    • 1.外部类属性:外部类类名.this.属性名
    • 2.内部类属性:this.属性名
    • 3.局部变量:属性名
  • 5.内部类对象的创建需要依赖外部类对象
    外部类类名.内部类类名 内部类对象名 = 外部类对象名.new 内部类类名
    
    在这里插入图片描述
  • 6.注意
    • 1.当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员,如果要访问外部类的同名成员,需要通过以下形式进行访问
      • 1.外部类.this.成员变量
      • 2.外部类.this.成员方法
    • 2.虽然成员内部类可以无条件地访问外部类的成员,但外部类想访问成员内部类的成员必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问

2.静态内部类

class 外部类类名{
    
	static class 内部类类名{
    
	
	}
}
class Outer {
    
   private static int staticVar = 20;
   static class StaticInner {
    
       void display() {
    
           System.out.println("StaticVar: " + staticVar);
       }
   }
}
  • 1.定义:使用static修饰符定义在类内部的类。它可以访问外部类的静态成员,但不能访问外部类的非静态成员(静态内部类的生命周期独立于外部类的实例,它不需要外部类的实例就可以被创建和使用,因此静态内部类无法访问外部类的非静态成员,因为非静态成员需要一个具体的外部类实例才能被访问)
  • 2.如果外部类属性,内部类属性,内部类局部变量出现重名
    • 1.访问外部类静态属性:外部类类名.属性名
    • 2.访问内部类静态属性:外部类类名.内部类类名.属性名
  • 3.静态内部类对象创建要依赖于外部类类名,可直接通过外部类类名.内部类类名.静态内容的方式直接访问内部类静态内容
    在这里插入图片描述

3.局部内部类

class 外部类类名{
    
	访问修饰符 返回值类型 方法名(参数列表){
    
		class 内部类类名{
    
		
		}
	}
}
class Outer {
    
   void method() {
    
       class LocalInner {
    
           void display() {
    
               System.out.println("Local inner class");
           }
       }
       LocalInner localInner = new LocalInner();
       localInner.display();
   }
}
  • 1.定义:定义在方法或构造器中,它的作用域仅限于定义它的方法或构造器,局部内部类不能有访问修饰符(如public、private等),因为它不是类的成员
  • 2.无法定义静态内容
  • 3.可以访问外部类的局部变量,但是该局部变量必须是常量(jdk7之前必须用final显式修饰,jdk8之后只需要没有再次更改值)
  • 4.局部内部类对象只能在所属的外部类方法中创建
  • 5.局部变量存储在方法的栈帧中,而局部内部类的对象可能在方法执行完毕后仍然存在(如局部内部类的对象被传递到其他方法或存储在某个字段中),如果局部变量不是final,那么在方法执行完毕后,局部变量的值可能会被修改,而局部内部类的对象仍然持有对该变量的引用,这会导致不一致的行为
class Outer {
    
   void method() {
    
       int localVar = 10;
       class LocalInner {
    
           void display() {
    
               System.out.println(localVar); // 如果localVar不是final,可能会导致问题
           }
       }
       LocalInner localInner = new LocalInner(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值