Skip to content
目录

Java 面向对象

面向对象基础

类和对象

  1. 类是抽象的,概念的,代表一类事物,即它是数据类型。
  2. 对象是具体的,实际的,代表一个具体事物,是实例。
  3. 类是对象的模板,对象是类的一个个体,对应一个实例。
  4. 类是对象的概括或者抽象,对象是类的实例化。

属性(字段,成员变量)

  • 属性的声明: [修饰符] 数据类型 变量名 [= 初始值];
  • 注意事项和细节
    • 1.属性和局部变量可以重名,访问时遵循就近原则
    • 2.在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名
    • 3.属性生命周期较长,局部变量生命周期较短
    • 4.作用域范围不同 全局变量/属性:可以被本类使用,或其他类使用
    • 5.修饰符不同 全局变量/属性可以加修饰符 局部变量不可以加修饰符

成员方法

[修饰符] 返回值类型 方法名([数据类型 参数名,……]){}

方法重载

  • Java 中允许同一个类中,多个同名方法的存在,但要求 形参列表不一致
  • 注意事项和使用细节
    • 方法名:必须相同
    • 形参列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)
    • 返回类型:无要求

可变参数

Java 允许同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。 类似 public void sell(String.... str){}

  • 注意事项和细节
    • 1.可变参数的实参可以为 0 个或任意多个
    • 2.可变参数的实参可以为数组
    • 3.可变参数的本质就是数组
    • 4.可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
    • 5.一个形参列表中出现一个可变参数

作用域

  1. 在 Java 编程中,主要的变量就是属性和局部变量
  2. 我们说的局部变量一般是指在成员方法中定义的变量
  3. Java 中作用域的分类
  • 全局变量:也就是属性,作用域为整个类体
  • 局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中
  1. 全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。

构造器

  1. 一个类可以定义多个不同的构造器,即构造器重载
  2. 构造器没和类名要相同
  3. 构造器美哟返回值
  4. 构造器是完成对象的初始化,并不是创建对象
  5. 在创建对象时,系统自动的调用该类的构造方法
  6. 如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器
  7. 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显式的定义一下。

this 关键字

哪个对象调用,this 就代表哪个对象

  • 注意事项和使用细节

    1. this 关键字可以用来访问本类的属性、方法、构造器
    2. this 用于区分当前类的属性和局部变量
    3. 访问成员方法的语法:this.方法名(参数列表)
    4. 访问构造器语法:this(参数列表),注意只能在构造器中使用 (即只能在构造器中访问另外一个构造器,必须放在第一条语句)
    5. this 不能再类定义的外部使用,只能在类定义的方法中使用。

面向对象中级

本质就是创建不同的文件夹/目录来保存类文件,package 关键字(表示打包),com.olderhard(表示包名)

包的三大作用

  1. 区分相同名字的类
  2. 当类很多时,可以很好的管理类
  3. 控制访问范围

访问修饰符

Java 提供四种访问控制修饰符号,用于控制方法和属性的访问权限

  1. 公开级别:public 修饰,对外公开
  2. 受保护级别:protected 修饰,对子类和同一个包中的类公开
  3. 默认级别:没有修饰符号,向同一个包的类公开
  4. 私有级别:private 修饰,只有类本身可以访问,不对外公开。

面向对象三大特征(封装,继承和多态)

封装

封装就是把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(方法),才能对数据进行操作。

  • 封装的实现步骤(3 步)
    1. 将属性进行私有化 private
    2. 提供一个公共的(public)set 方法,用于对属性判断并赋值
    3. 提供一个公共的(public)get 方法,用于获取属性的值

继承

继承可以解决代码复用,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。子类继承父类,子类继承父类的属性和方法,子类同时可以加一些自己特有的属性和方法。

  • 注意事项和细节
    1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
    2. 子类没有继承父类的构造器,但必须调用父类的构造器,完成父类的初始化
    3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化。
    4. super 在使用时,必须放在构造器第一行,super 和 this 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
    5. Java 所有类都是 Object 类的子类,Object 是所有类的基类
    6. 父类构造器的调用不限于直接父类,将一直往上追溯直到 Object 类
    7. 子类最多只能继承一个父类,在 Java 中是单继承机制
    8. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
  • super 关键字
    • super 代表父类的引用,用于访问父类的属性、方法、构造器
  • 基本语法
    1. 访问父类的属性,但不能访问父类的 private 属性
    2. 访问父类的方法,不能访问父类的 private 方法
    3. 访问父类的构造器:super(参数列表)
  • 方法的重写
    • 方法重写(覆盖)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法。
    • 注意事项和使用细节
      1. 子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样
      2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
      3. 子类方法不能缩小父类方法的访问权限

多态

方法或对象具有多种形态,多态是建立在封装和继承基础之上的。

  • 多态的具体体现
    • 1.方法的多态:重写和重载就体现多态
    • 2.对象的多态:
      • (1).一个对象的编译类型和运行类型可以不一致
      • (2).编译类型在定义对象时,就确定了,不能改变,
      • (3).运行类型时可以变化的。
  • 注意事项和细节
    • 多态的前提是,两个对象(类)存在继承关系
    • 多态的向上转型
      1. 本质:父类的引用指向了子类的对象
      2. 语法:父类类型 引用名= new 子类类型();
      3. 特点:可以调用父类中的所有成员,不能调用子类中特有成员,最终运行效果看子类的具体实现(动态绑定机制)
    • 多态的向下转型 1.语法:子类类型 引用名 = (子类类型) 父类引用 2.只能强转父类的引用,不能强转父类的对象 3.要求父类的引用必须指向的是当前目标类型的对象。 4.当向下转型后,可以调用子类类型中所有的成员。 5.属性没有重写之说,属性的值看编译类型
  • java 的动态绑定机制 1.当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定 2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。
  • 多态的应用
    • 多态数组:数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
    • 多态参数:方法定义的形参类型为父类类型,实参类型允许为子类类型

Object 类详解 (Object 中的方法)

  • equals(Object a) :只能判断引用类型。与==不同,==基本数据类型判值,引用类型判地址。
  • finalize() : 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
  • getClass()
  • hashCode() : 返回该对象的哈希码值。
  • toString() : 返回该对象的字符串表示。

面向对象高级

类变量和类方法(static 所修饰的)

  1. 一个类的静态变量会被该类的所有对象所共享。
  2. 当一个方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率。在程序员实际开发,往往将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用了。
  3. 静态变量可以应用于普通方法和静态方法,普通变量只能应用于普通方法,不能应用于静态方法。同义,静态方法只能调用静态属性,普通方法可调用所有属性。

main 主方法 (形式:public void main(String[] args){})

  1. JVM 虚拟机调用 main 方法
  2. Java 虚拟机需要调用类的 main()方法,所以该方法的访问权限必须是 public
  3. Java 虚拟机在执行 main()方法时,不必创建对象,所以该方法必须是 static
  4. 该方法接收 String 类型的数组参数,该数组中保存执行 Java 命令时,传递所运行的类的参数(形似:java 运行程序名 参数 1 参数 2 参数 3)

代码块

  • 代码块又称为初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显示调用,而是加载类时,或创建对象时隐式调用。
  • 理解:
    • 代码块相当于对构造器的补充机制,可以做初始化的操纵。例如,当多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重要性。

单例模式

  1. 所谓类的单例设计模式,就是采用一定的方法保证整个的软件系统中,对某个类只能存在一个对象实例,并且该类值提供一个取得其对象实例的方法
  2. 单例模式有两种方式:饿汉式,懒汉式
  • 饿汉式和懒汉式的实现步骤
    1. 构造器私有化
    2. 类的内部创建对象
    3. 向外暴露一个静态的公共方法

final 关键字

  • final 可以修饰类、属性、方法和局部变量
  • 当不希望类被继承时,可以用 final 修饰
  • 当不希望父类的某个方法没子类重写时,可以用 final 修饰
  • 当不希望类的某个属性的值被修改时,可以用 final 修饰
  • 当不希望某个局部变量被修改,可以使用 final 修饰

抽象类

  • 父类方法的不确定性导致的,当父类的某些方法,需要声明,但是又不确定如何实现时,科技将其声明为抽象方法,那么这个类就是抽象类(abstract)。
  • 抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

接口

在 Java 中接口不仅仅是程序开发过程中“约定”,更是更加抽象化的抽象类,对抽象类的进一步抽象,给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。

  • 注意事项和细节
    1. 接口不能被实例化,没有 new AI();
    2. 抽象类实现接口,可以不用实现接口的方法,但是一个普通类实现接口,必须将该接口的所有方法都实现。 浅显地说,这个接口是将一些没有实现的方法封装到一起,当一些不同的类要实现这些方法的时候,可以提供一个接口,让这些不同的类来实现。这样当调用这些类的方法的时候,会统一的调用,大大降低了一种情况——功能方法相同时,名字不同。
    3. 接口中的属性都是 public static final 的,当然定义的时候可以不用这么写,但一定要有值,访问接口属性方式:接口名.属性名
    4. 一个类可以同时实现多个接口。
    5. 接口和接口之间存在继承关系,接口可以继承多个别的接口 继承的价值主要在于:解决代码的复用性和可维护性 接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法。
    6. 浅显地说,想使用一个接口,要写一个类,实现该接口,并创建该类的对象。当然还可以使用匿名类的方式,调用该接口,不过到时候得重新实现每个方法,还只能用一次。
    7. 接口的多态特性
    • 类似继承的多态,接口是编译类型,实现接口方法的类是运行类型,如多态参数,多态数组。
    • 接口的多态的传递现象,interface A{}, interface B extends A{},实现了 B 接口的类,也实现了 A 接口。

内部类

  • 一个类的内部又完整的嵌套了另一个类结构。内部类的最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。
  • 如果定义在局部位置(方法内部/代码块内部)有两种:局部内部类,匿名内部类 如果定义在成员位置(类似属性和方法的位置)有两种:成员内部类,静态内部类

局部内部类【相当于局部变量】

  • 定义在 局部位置(方法或代码块) 中且有类名,正常类
  • 作用:可以直接访问外部类的所用成员,包含私有的,例如 外部类名.this.属性。
  • 外部类要访问内部类,需要在该方法中创建内部类的对象,再调用它的方法。

匿名内部类(简化开发)

  • 本质是类,内部类,该类没有名字,同时还是一个对象,定义在 局部位置(方法或代码块) 中。
  • 当你想使用一个类和接口时,并且只使用一次,就可以类似的操作,IA 是一个接口,IA a =new IA(){ 实现接口方法;};系统会创建一个匿名的类 类似就是 class XXXX implements IA{实现接口方法};,创建实例 ,a 再指向这个实例,结束。
  • 接口是创建一个类;类是创建一个子类,其中的方法可以重写。
  • 匿名内部类跟局部内部类一样,在它的方法中可以访问外部类的所有东西
  • 匿名内部类应用:【可以当做一个实参直接传递】(例如在使用接口的时候,就不用那么麻烦地使用,虽然只能用一次)

成员内部类

  • 定义在外部类的成员位置,类的属性和方法的位置,不是局部变量,是外部类的一个成员
  • 成员内部类访问-->外部类的东西:直接访问;
  • 外部类访问-->成员内部类的东西:创建对象,再访问;
  • 外部其他类访问-->成员内部类的东西,创建对象,再访问;

静态内部类

  • 定义在外部类的成员位置,并且有 static 修饰
  • 静态内部类可以访问外部类的所有静态成员,但不能直接访问非静态成员。
  • 静态内部类访问-->外部类 :可直接访问它的所有静态成员
  • 外部类访问-->静态内部类:创建对象,再访问;
  • 外部其他类访问-->静态内部类;

常用类

一、包装类

针对八种基本数据类型,相应的引用类型——包装类

  • boolean—Boolean;char—Character;byte—Byte;short—Short;int—Integer;long—Long;float—Float;double—Double;
  • 包装类与基本数据类型相互转换,直接转,底层已经帮助实现;
  • 包装类与 String 互相转换
    • Integer.toString ,StringvalueOf(Integer),Interger+"";
    • Interger.valueOf(String),Integer.parseInt(String),new Integer(String);

二、String 类

  • String 是 final 类型的!!!,所以它改,肯定是新的。
  • String 可以串行化,属性有 final char[] value,String 是 final 类
  • String 的常用方法
    • equals,equalslgnoreCase,length,indexOf,lastIndexOf,substring(l,r),trim,charAt(i),toUpperCase,toLowerCase,concat,replace,split,compareTo,toCharArray,format;
    • char[] c=s.toCharArray();
    • String p=s.substring(s.begin(),s.end());
    • String p=String.format("%s %d",name,age);

三、StringBuffer 类

  • StringBuffer 代表可变字符序列,可以对字符串内容进行增删,很多方法与 String 相同,但 StringBuffer 是可变长度的,StringBuffer 是一个容器。
  • StringBuffer 的对象可以串行化,父类中属性有 char[] value,StringBuffer 是 final 类,已同步,线程安全;

四、StringBuilder 类

  • 几乎跟 StringBuffer 相同,不过是未同步,效率最高;
  • String vs StringBuffer vs StringBuilder的选择
    1. 如果字符串存在大量的修改操作,一般使用 StringBuffer 或 StringBuilder
    2. 如果字符串存在大量的修改操作,并在单线程的情况下,使用 StringBuffer
    3. 如果字符串存在大量的修改操作,并在多线程的情况下,使用 StringBuider
    4. 如果我们字符串很少修改,被多个对象引用,使用 String,比如配置信息等

五、Math 类

  • Math 的方法都是静态的方法,可以直接使用,不用创建对象
  • 随机数: int ans=(int)(a+Math.random()*(b-a+1)); //范围[a,b]
  • 向上取整,向下取整:ceil,floor;

六、Arrays 类

  • Arrays 里面包含一系列静态方法,用于管理或操作数组,比如排序和搜索 (使用的对象是类,也可以是自定义的类),copyOf()、fill()、equals、asList
Arrays.toString(a);
Arrays.sort()
Integer[] a={0,2,3,54,6};
System.out.println(Arrays.toString(a));
Integer[] b=Arrays.copyOf(a,a.length);
Arrays.fill(a,1);
Arrays.sort(books, new Comparator<Book>() {    //自定义比较方法,特重要!
@Override
public int compare(Book o1, Book o2) {
return 1;
}
});

七、System 类

  • 跟系统相关的类
  • System.exit(0)
  • System.currentTimeMillis() //返回当前时间距离 1970-1-1 00:00 的毫秒数

八、BigInterger 和 BigDecimal 类

  • BigInteger 适合保存比较大的整型;
  • BigDecimal 适合保存精度更高的浮点型(小数)
  • 不过对于这两个类的数,不能直接进行运算,得调用这两个类的方法哦!

九、日期类

  1. Date 类:精确到毫秒,代表特定的瞬间,第一代
  • 这里的 Date 是指的是在 java.util 包下的 Date
Date date=new Date();
System.out.println(date); //系统当前时间,默认输出格式:Tue Jul 30 11:34:54 CST 2024
  • 创建 SimpleDateForma 对象,可以指定相应格式(特定的)
SimpleDateFormat s = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
System.out.println(s.format(date)); //输出:2024年07月30日 11:43:27 周二
Date d=s.parse(s.format(date)); //也能将规范的格式,转回来
  1. Calendar 类:日历,第二代
  • 抽象类,构造器是 private,通过 getInstance()获取实例对象,提供大量的方法和字段
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR)); //返回字段信息
  1. 第三代 (补充 Date 和 Calendar 的不足) LocalDate(日期) ,LocalTime(时间) ,LocalDateTime(日期时间);
LocalDate b= LocalDate.now();
LocalTime c= LocalTime.now();
LocalDateTime a =LocalDateTime.now();
DateTimeFormatter d=DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH小时mm分钟ss秒");
System.out.println(d.format(a)); //格式化LocalDateTime 时间
  • Instant(时间戳,类似 Date)
Instant i =Instant.now();

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情