admin管理员组

文章数量:1565357

JavaSE笔记

文章目录

  • JavaSE笔记
    • 第一章 初识Java
      • 1.1 java发展史
      • 1.2 特点
      • 1.3 语言特性
      • 1.4 JDK、JRE、JVM三者关系
      • 1.5 Java加载与执行
      • 1.6 DOS基本命令
      • 1.7 常用快捷键
      • 1.8 Java环境搭建
      • 1.9 注释
    • 第二章 数据相关
      • 2.1 标识符与关键字
      • 2.2 变量
        • 2.2.1 字面量
        • 2.2.2 变量
      • 2.3 数据类型
        • 2.3.1 定义
        • 2.3.2 8种基本数据类型区别
        • 2.3.3 数据类型注意事项
        • 2.3.4 字符编码
        • 2.3.5 转义字符
      • 2.4 运算符
        • 2.4.1 算数运算符
        • 2.4.2 关系运算符
        • 2.4.3 逻辑运算符
        • 2.4.4 赋值运算符
        • 2.4.5 三目运算符
        • 2.4.6 移位运算符
        • 2.4.7 字符串拼接
        • 2.4.8 优先级
    • 第三章 控制语句
      • 3.1 键盘输入语句
      • 3.2 if语句
      • 3.3 switch语句
      • 3.4 for语句
      • 3.5 while语句
      • 3.6 do while语句
    • 第四章 方法
      • 4.1 语法
      • 4.2 方法的内存层面
      • 4.3 方法重载overload
      • 4.4 方法递归
    • 第五章 面向对象
      • 5.1 类
        • 5.1.1 类和对象的关系
        • 5.1.2 类的创建
        • 5.1.3 类的实例化(创建对象)
        • 5.1.4 (内存)运行过程
        • 5.1.5 构造方法
      • 5.2 封装
        • 5.2.1 什么是封装
        • 5.2.2 封装步骤
      • 5.3 继承
        • 5.3.1 继承机制
        • 5.3.2 继承特性
        • 5.3.3 方法覆盖(重写)
      • 5.4 多态
        • 5.4.1 什么是多态
        • 5.4.2 基础语法
        • 5.4.3 instanceof运算符
      • 5.5 this和super
      • 5.6 修饰符
        • 5.6.1 权限修饰符
        • 5.6.2 特征修饰符
          • static
          • final
          • abstract(抽象类)
          • interface(接口)
      • 5.7 Object类
        • 5.7.1 toString()
        • 5.7.2 equals()
        • 5.7.3 finalize
      • 5.8 包和import
        • 5.8.1 package
        • 5.8.2 import
        • 5.8.3 JDK常用包
      • 5.9 内部类
    • 第六章 数组
      • 6.1 数组简介
        • 6.1.1 数组扩容
      • 6.2 数组常用算法
        • 6.2.1 冒泡排序
        • 6.2.2 选择排序
        • 6.2.3 数组二分法查找
      • 6.4 Arrays工具类
        • 6.4.1 Arrays.length 数组长度
        • 6.4.2 Arrays.sort 数组排序(小到大)
        • 6.4.3 Arrays.binarySerch() 二分查找
        • 6.4.4 Arrays.toString() 数组的打印
        • 6.4.5 Arrays.fill() 数组的填充
        • 6.4.6 Arrays.equals() 判断两个数组大小是否相等
        • 6.4.7 Arrays.copyOf() 数组的拷贝
    • 第七章 常用类
      • 7.1 String
        • 7.1.1 String 特点
        • 7.1.2 String 常用方法
      • 7.2 StringBuffer 和 StringBuilder
      • 7.3 包装类
      • 7.4 日期类
        • 7.4.1 Date类
        • 7.4.2 SimpleDateFormat类
        • 7.4.3 Calendar类
      • 7.5 数字类
        • 7.5.1 Math类
        • 7.5.2 BigDecimal类
      • 7.6 Random
      • 7.7 枚举
        • 7.7.1 枚举常用方法
        • 7.7.2 枚举的高级使用
        • 7.7.3 枚举中的抽象类
        • 7.7.4 枚举的其他用法
    • 第八章 异常
      • 8.1 异常的分类
        • 8.1.1 什么是Throwable
        • 8.1.2 Exception及其子类
      • 8.2 异常的捕获
        • 8.2.1 try、catch 和 finally
        • 8.2.2 获取异常信息方法
      • 8.3 throw和throws
      • 8.4 自定义异常
    • 第九章 集合
      • 9.1 集合的结构
        • 9.1.1 集合概述
        • 9.1.2 集合继承关系
        • 9.1.3 集合和数组的区别
      • 9.2 Iterable和Collection
        • 9.2.1 Iterable接口
        • 9.2.2 Collection接口
      • 9.3 List
        • 9.3.1 ArrayList(数组)
        • 9.3.2 LinkedList(双向链表)
      • 9.4 Set
        • 9.4.1 哈希表、二叉树
        • 9.4.2 HashSet(Hash 表)
        • 9.4.3 TreeSet(二叉树)
        • 9.4.4 LinkHashSet(HashSet+LinkedHashMap)
        • 9.4.5 小结
      • 9.5 Map
        • 9.5.1 HashMap
        • 9.5.2 TreeMap
      • 9.6 Collections工具类
      • 9.7 泛型
        • 9.7.1 泛型的使用
        • 9.7.2 JDK8 泛型新特性
    • 第十章 IO流
      • 10.1 IO流概述
        • 10.1.1 InputStream 字节输入流
        • 10.1.2 OutputStream 字节输出流
        • 10.1.3 Reader 字符输入流
        • 10.1.4 Writer 字符输出流
      • 10.2 文件流
        • 10.2.1 FileInputStream(文件字节输入流)
        • 10.2.2 FileOutputStream(文件字节输出流)
        • 10.2.3 FileReader(文件字符输入流)
        • 10.2.3 FileReader(文件字符输入流)
      • 10.3 缓冲流
        • 10.3.1 字节缓冲流
        • 10.3.2 字符缓冲流
      • 10.4 转换流
        • 10.4.1 InputStreamReader
        • 10.4.2 OutputStreamWriter
      • 10.5 打印流
        • 10.5.1 完成屏幕打印的重定向
        • 10.5.2 接受屏幕输入
      • 10.6 对象流
        • 10.6.1 序列化
        • 10.6.2 反序列化
        • 10.6.3 serialVersionUID
      • 10.7 File 类
        • 10.7.1 File 类常用方法
    • 第十一章 多线程
      • 11.1 多线程的基本概念
        • 11.1.1 进程简介
        • 11.1.2 线程简介
        • 11.1.3 并行与并发
        • 11.1.4 java程序的执行流程
      • 11.2 线程的生命周期
      • 11.3 两种线程实现方式
        • 11.3.1 继承 Thread 类
        • 11.3.2 实现 Runnable 接口
        • 11.3.3 两种方式比较
      • 11.4 线程调度与控制
        • 11.4.1 线程的优先级
        • 11.4.2 Thread.sleep 线程睡眠
          • sleep与wait区别
        • 11.4.3 Thread.yield 线程让步
        • 11.4.4 Thread.join 线程插入
        • 11.4.5 Thread.interrupt 线程中断
        • 11.4.6 推荐的停止线程方式
      • 11.5 Thread类常用方法
      • 11.6 线程锁
        • 11.6.1 乐观锁
        • 11.6.2 悲观锁
        • 11.6.3 自旋锁
        • 11.6.4 Synchronized 同步锁
      • 11.7 守护线程
    • 第十二章 反射
      • 12.1 反射的基本概念
      • 12.2 反射的使用
        • 12.2.1 反射使用场合
        • 12.2.2 反射API
        • 12.2.3 使用步骤
        • 12.2.4 获取class对象的3种方法
        • 12.2.5 创建对象的两种方法
      • 12.3 反射的缺点

第一章 初识Java

1.1 java发展史

​ 1990 年末,Sun 公司准备为下一代智能家电(电视机,微波炉,电话)编写一个通用的控制系统。该团队最初考虑使用C++语言,很多成员包括Sun 公司的首席科学家Bill Joy,发现C++语言在某些方面复杂,系统资源极其有限,缺少垃圾回收系统等,于是Bill Joy 决定开发一种新的语言:Oak。

​ 1992 年夏天,Green 计划已经完成新平台的部分功能,包括Green 操作系统,Oak 的程序设计语言、类库等。同年11 月,Green 计划被转成“FirstPerson 有限公司”,一个Sun 公司的全资子公司。该团队致力于创建一种高度互动的设备。

​ 1994 年夏天,互联网和浏览器的出现不仅给广大互联网的用户带来了福音,也给Oak 语言带来了新的生机。James Gosling(Java 之父)立即意识到,这是一个机会,于是对Oak 进行了小规模的改造。

​ 1994 年秋,小组中的Naughton 和Jonathan payne 完成了第一个Java 语言的网页浏览器:WebRunner。Sun 公司实验室主任Bert Sutherland 和技术总监Eric Schmidt 观看了该网页的演示并给予了高度的评价。当时Oak 这个商标已经被注册了,于是将Oak 改名为Java。

​ 1995 年初,Sun 公司发布Java 语言,Sun 公司直接把Java 放到互联网上,免费给大家使用,甚至连源代码也不保密,也放在互联网公开。几个月后,Java 成了互联网上最热门的宝贝。各种各样的小程序层出不穷,Java 终于扬眉吐气,成为了一种广为人知的编程语言。

​ 1996 年底,Flash 问世了,这是一种更加简单的动画设计软件:使用Flash 几乎无须任何编程语言知识,就可以做出丰富多彩的动画。Flash 逐渐蚕食了Java 在网页上的应用。

​ 1997 年2 月18 日,Sun 公司发布了JDK1.1,增加了即时编译器JIT。

​ 1995 年Java 诞生到1998 年底,Java 语言虽然成为了互联网上广泛使用的编程语言,但它没有找到一个准确的定位。

​ 1998 年12 月,Sun 发布了Java 历史上最重要的JDK 版本:JDK1.2。并将Java 分成了J2EE(提供了企业应用开发相关的完整解决方案)、J2SE(整个Java 技术的核心和基础)、J2ME(主要用于控制移动设备和信息家电等有限存储的设备)三个版本。

​ 2002 年2 月,Sun 发布了JDK 历史上最为成熟的版本,JDK1.4。

​ 2004 年10 月,Sun 发布了万众期待的JDK1.5。JDK1.5 增加了诸如泛型、增强的for 语句、可变数量的形参、注释、自动拆箱和装箱等。

​ 2005 年,Java 诞生十周年,J2SE/J2EE/J2ME 分别改名为:JavaSE/JavaEE/JavaME。2006 年12 月,Sun 发布了JDK1.6。

​ 2009 年4 月20 日,Oracle 甲骨文公司宣布将以每股9.5 美元的价格收购Sun。Oracle 通过收购Sun 获得了两项资产:Java 和Solaris。

​ 2007 年11 月,Google 宣布推出一款基于Linux 平台的开源手机操作系统:Android。Android使用Java 语言来开发应用程序。Android 平台的流行,让Java 语言获得了在客户端程序上大展拳脚的机会。

​ 2011 年7 月28 日,Oracle 发布了Java SE7,这次版本升级耗时将近5 年时间。引入二进制整数、支持字符串的switch 语句等。

​ 2014 年3 月18 日,Oracle 发布了Java SE 8。2017 年7 月,Oracle 发布了JavaSE 9。

​ 2018 年3 月20 日,Oracle 发布了正式版JavaSE 10。同一年9 月25 日发布了Java11。

​ 2019 年3 月19 日,Oracle 发布了Java12。

​ 2019 年 9 月,Oracle 发布了Java SE 13

​ 2020 年 3 月,Oracle 发布了Java SE 14

1.2 特点

Java分别为三部分:JavaSE、JavaEE、JavaME。三者关系如下图:

JavaSE 是Java 的标准版,是学习JavaEE 和JavaME 的基础,JavaEE 是企业版,JavaME 是微型版。

1.3 语言特性

简单性:Java 语言底层采用C++语言实现,相对于C++来说,Java 是简单的,在Java语言中程序员不需要再操作复杂的指针(指针的操作是很复杂的),继承方面也是只支持单继承(C++语言是一种半面向对象的编程语言,支持多继承,多继承会导致关系很复杂),在很多方面进行了简化。

面向对象:Java 中提供了封装、继承、多态等面向对象的机制。

健壮性:在C++程序当中的无用数据/垃圾数据需要编程人员手动释放,当忘记释放内存的时候,会导致内存使用率降低,影响程序的执行;在Java 语言当中这种问题得到了解决,因为Java 语言引入了自动垃圾回收机制(GC 机制),Java 程序启动了一个单独的垃圾回收线程,时刻监测内存使用情况,在特定时机会回收/释放垃圾数据,这样会让内存时刻处于最好的状态。

多线程:Java 语言支持多个线程同时并发执行,同时也提供了多线程环境下的安全机制。

可移植性/跨平台:可移植性/跨平台表示Java 语言只需要编写/编译一次,即可通过JVM处处运行。

Java程序在计算机的结构:

1.4 JDK、JRE、JVM三者关系

① JDK:JDK(Java Development Kit)是Java 语言的软件开发工具包(SDK)。它是每一个Java 软件开发人员必须安装的。JDK 安装之后,它会自带一个JRE,因为软件开发人员编写完代码之后总是要运行的。注意:如果只是在这台机器上运行Java 程序,则不需要安装JDK,只需要安装JRE 即可。

② JRE:JRE(Java Runtime Environment,Java 运行环境),运行JAVA 程序所必须的环境的集合,包含JVM 标准实现及Java 核心类库。

③ JVM:JVM 是Java Virtual Machine(Java 虚拟机)的缩写,JVM 是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM 是实现Java 语言跨平台的法宝。

JDK、JRE、JVM 之间存在这样的包含关系:JDK 包含JRE,JRE又包含JVM。换句话说,只要安装了JDK,JRE 和JVM 则自动就安装了。

1.5 Java加载与执行

写代码–>编译–>运行

① 编写java源代码,保存为“.java”结尾的文件。

② 使用“javac”命令对java源文件进码行编译,生成“.class”结尾的字节码文件。“.class”前的文件名称为类名

③ 使用“java”命令启动JVM虚拟机,JVM通过“类加载器ClassLoader”从硬盘中找到A.class文件并装载,JVM再将字节码转换为二进制码郊游操作系统执行。

1.6 DOS基本命令

  • Win + R 打开命令窗口;输入“cmd”打开DOS窗口
  • 创建目录:/mkdir xxx
  • 切换盘符:/d: or /e:
  • 打开文件夹:/cd 路径
  • 当前目录详情:/dir
  • 清屏:/cls
  • 返回上级目录:/cd …
  • 返回根目录:/cd \
  • 退出DOS:/exit
  • 删除文件:/del xx or /del *xx (删除含关键字文件)
  • 查看本机IP:/ipconfig or /ipconfig /all (更详细)
  • 测试网络状态:/ping www.abc -t (-t是持续检测)

1.7 常用快捷键

  • 复制:ctrl + c
  • 粘贴 ctrl + v
  • 剪切 ctrl + x
  • 保存 ctrl + s
  • 全选 ctrl + a
  • 查找 ctrl + f
  • 撤销 ctrl + z
  • 重做 ctrl + y
  • 回到行首 home键(fn + ←)
  • 回到行尾 end键(fn + →)
  • 选中一行 shift + home/end
  • 回到文件头 ctrl + home
  • 回到文件尾 ctrl + end
  • 选中一个字母 shift + ←/→
  • 选中一个单词 鼠标双击/ctrl + shift + ←/→
  • 选中一行 鼠标三击

1.8 Java环境搭建

① 安装JDK:搜索oracle官网下载并安装JDK

② 配置环境变量:在桌面上“计算机”图标上点击右键->属性->高级系统设置->环境变量。在系统变量中找到path,添加JDK的bin文件目录,例如:C:\Program Files\Java\jdk-9.0.4\bin

③ 检查Java是否可用:/java -version or /javac -version

④ 第一个Java程序HelloWorld:

​ 新建一个HelloWorld.java文件

public class HelloWorld {
   
    public static void main(String[] args) {
   
        System.out.println("HelloWorld!");
    }
}

​ 编译:/javac d:/app/xxx.java (快捷方式:/javac + 将文件拖入窗口)

​ 运行:在字节码所在目录下/java 类名

1.9 注释

第一种:单行注释

// 斜杠后面的内容会被注释

第二种:多行注释

/*xxxxxxxxx*/    //符号*之中的内容不管有多少行全部被注释

第三种:javadoc注释

/*** 这里的信息是javadoc 注释
* @author 作者名字
* @version 版本号
* @since 自从哪个版本号开始就存在了
*/
该注释可在后期生成帮助文档

第二章 数据相关

2.1 标识符与关键字

  • 标识符包括:类名、方法名、变量名、接口名、常量名… …

  • 命名规则:

    1.标识符只能由数字、字母、下划线、符号$ 组成

    2.标识符不能以数字开头

    3.关键字不能做标识符

    4.标识符严格区分的大小写

  • 命名规范:

    1.见名知意(标识符最好有实际意义)

    2.驼峰式命名(标识符中每个单词的首字母大写)

    3.类名、接口名特殊要求(首字母大写,后面的每个单词首字母大写)

    4.变量名、方法名特殊要求(首字母小写,后面的每个单词首字母大写)

    5.常量名特殊要求(全部大写,单词与单词之间下划线衔接)

  • 关键字:

    Java关键字是编程语言中事先定义具有特殊意义的单词,标识符命名不能和关键字冲突

2.2 变量

2.2.1 字面量

数据被分为:整数型、浮点型、字符型、布尔型、字符串型等。

​ 整数型:1 2 4 99 -1 -2 … …

​ 浮点型:1.3 3.33 … …

​ 布尔型:ture、false

​ 字符型:‘a’、‘b’、‘中’ … …

​ 字符串型:“aba”、“a”、“b”、“中国”、“中” … …

2.2.2 变量

变量就是存数据的盒子

内存中最基本的储存单元变量三要素:数据类型变量名

Java中,变量需先声明,再赋值才能访问,变量没有赋值,编译报错

根据位置分类:

​ 在方法体中声明的变量叫做局部变量

​ 在方法体外及类体内声明的变量叫做成员变量

变量只能作用在对应域内(花括号内,出了花括号就不认识)

2.3 数据类型

2.3.1 定义

数据类型是用来声明变量,程序在运行过程中根据不同的数据类型分配不同大小的空间。

数据分为:基本数据类型、引用数据类型

​ 第一种:基本数据类型

​ 基本数据类型又分为4大类8小种

​ 第一类:整数型

​ 第二类:浮点型

​ 第三类:布尔型

​ 第四类:字符型

​ 8小种:

​ byte,short,int,long

​ float,double

​ boolean

​ char

​ 第二种:引用数据类型

​ Java中除基本数据类型之外,剩下的都是引用数据类型

2.3.2 8种基本数据类型区别

十进制转为二进制:

二进制转为十进制:

2.3.3 数据类型注意事项

整数型:

  • java中整数会自动视为为int型,数值超过-2147483678~2147483647,后面要加L
  • 大容量数据类型赋值给小容量前,要强制类型转换,否则会损失精度编译报错
    • long a = 100L;
    • int b = (int)a;
  • byte型和short型在取值范围内,字面量可以直接赋值不用强制转换
  • 多种数据类型混合运算时,结果取最大容量的数据类型

浮点型:

  • 任意一个浮点型数据都比整数型容量空间大 float容量 > long容量
  • 任意一个浮点型数据都被默认当成double型数据处理

布尔型:

  • java中boolean类型只能有两个值,只能赋值为true和false(和C、C++不同)
2.3.4 字符编码

常见的字符编码有:

ASCII('a’是97,'A’是65,'0’是48)

ISO-8859-1

GB2312

GBK

GB18030

Big5

unicode(utf8 utf16 utf32)

Java中大部分团队使用的编码为utf-8

2.3.5 转义字符

常用转义字符:

制表符:\t

换行符:\n

输出符号:\ \' \" \: ... ...

转义unicode码:\u

2.4 运算符

2.4.1 算数运算符

​ 加减乘除:+ - * /

​ 取余:%

​ 自加1自减1:++ --

2.4.2 关系运算符

​ 大于:>

​ 大于或等于:>=

​ 小于:<

​ 小于或等于:<=

​ 等于:==

​ 不等于:!=

规则:所有关系运算符的运算结果都是布尔类型,不是true就是false;“==”和“=”注意区分,一个是判断,一个是赋值

2.4.3 逻辑运算符

​ 且:&

​ 或:|

​ 非:!

​ 短路与:&&

​ 短路或:||

规则:逻辑运算符两边必须是布尔类型

短路:当使用短路&&时,左边表达式为false时,右边表达式不执行;短路或||同理

2.4.4 赋值运算符

= += -= *= /= %=

规则:使用扩展赋值运算符不会改变运算结果类型,但是超数值范围用+=会损失精度

byte a = 10;
a += 1;    //a = (byte)(a + 1);

注:对于对象来说,= 赋值的不是对象的值,而是对象的引用

2.4.5 三目运算符

​ 语法格式:

​ 布尔表达式 ? 表达式1 : 表达式2

​ 布尔表达式结果为true时,表达式1为整条语句的结果;

​ 布尔表达式结果为false时,表达式2为整条语句的结果;

2.4.6 移位运算符

2.4.7 字符串拼接

​ “+” 两边是数字类型时,求和

​ “+” 任意一边是字符串类型的时候,进行字符串拼接,结果为字符串类型

2.4.8 优先级

第三章 控制语句

3.1 键盘输入语句

java.util.Scanner s = new java.util.Scanner(System.in);
int xx = s.nextInt();        //接收一个整数
String xx = s.next();        //接收一个字符串

3.2 if语句

3.3 switch语句

3.4 for语句

3.5 while语句

3.6 do while语句

第四章 方法

4.1 语法

[修饰符列表] 返回值类型 方法名(形式参数列表){
   
    方法体;        //由java语句构成
}

[]中括号中内容可选,不是必须的

注意事项:

​ 返回值可以是任何数据类型,不返回值时则标注void关键字

​ 形式参数可以有多个,每个参数都是局部变量,方法结束后内存释放

​ 标有static的方法,直接通过“类名.方法(实际参数)”调用,在同一个类时,“类名.”可省略

4.2 方法的内存层面

方法的调用称为压栈(入栈),方法的结束称为弹栈(出栈)。

当应用启动时,main方法压栈,main方法调用其他方法时,a1方法入栈,形成一层叠一层的模式。

方法结束时,必须由栈顶方法先弹栈,再依次结束。

4.3 方法重载overload

方法功能相似时,将方法名一致构成重载,使代码更加美观

调用重载方法时,Java 编译器能通过检查调用的方法的参数类型和个数选择一个恰当的方法。

条件:

​ 在同一个类

​ 方法名相同

​ 参数列表不同(个数、类型、顺序)

注意:方法重载和修饰符列表无关、和返回值类型无关,和参数变量名字无关

4.4 方法递归

方法体中自己调用自己:

public static void sum(){
   
    sum();
}

第五章 面向对象

术语:面向对象编程:OOP(Object-Oriented Programming)

面向对象三大特征:

封装(Encapsulation)

继承(Inheritance)

多态(Polymorphism)

什么是面向对象和面向过程:

​ 面向过程其实是最为实际的一种思考方式,就算是面向对象的方法也是含有面向过程的思想。可以说面向过程是一种基础的方法。它考虑的是实际地实现。一般的面向过程是从上往下步步求精。面向对象主要是把事物给对象化,对象包括属性与行为。当程序规模不是很大时,面向过程的方法还会体现出一种优势。因为程序的流程很清楚,按着模块与函数的方法可以很好的组织。但对于复杂而庞大的系统来说,面向过程显得就很无力了。

​ 为了帮助大家理解面向过程和面向对象,我们再来设想一个场景,假如说编写一段程序,模拟一个人抽烟的场景,采用面向过程的方式是这样的:买烟->买打火机->找能够抽烟的场合->点燃香烟->开抽,只要按照这个流程一步一步来,就可以实现抽烟场景,采用面向对象的方式关注点就不一样了,我们会想这个场景都有什么事物参与,每个事物应该有什么行为,然后将这些事物组合在一起,来描述这个场景,例如:一个会抽烟的人(对象)+香烟(对象)+打火机(对象)+允许抽烟的场所(对象),将以上4 个对象组合在一起,就实现了抽烟场景,其中采用面向对象的方式开发具有很强的扩展力,例如:人这个对象是可以更换的,打火机也是可以更换的,香烟的品牌也是可以更换的,包括抽烟的场合也是可以更换的。如果采用面向过程方式开发,一步依赖另一步,任何一步都不能变化,变化其中一步则整个软件都会受到影响。

​ 网上发现了一篇文章,说了一下OP 与OO 的不同,并且打了一个比喻,通俗易懂。有人这么形容OP 和OO 的不同:用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。所谓盖浇饭,北京叫盖饭,东北叫烩饭,广东叫碟头饭,就是在一碗白米饭上面浇上一份盖菜,你喜欢什么菜,你就浇上什么菜。我觉得这个比喻还是比较贴切的。蛋炒饭制作的细节,我不太清楚,因为我没当过厨师,也不会做饭,但最后的一道工序肯定是把米饭和鸡蛋混在一起炒匀。盖浇饭呢,则是把米饭和盖菜分别做好,你如果要一份红烧肉盖饭呢,就给你浇一份红烧肉;如果要一份青椒土豆盖浇饭,就给浇一份青椒土豆丝。蛋炒饭的好处就是入味均匀,吃起来香。如果恰巧你不爱吃鸡蛋,只爱吃青菜的话,那么唯一的办法就是全部倒掉,重新做一份青菜炒饭了。盖浇饭就没这么多麻烦,你只需要把上面的盖菜拨掉,更换一份盖菜就可以了。盖浇饭的缺点是入味不均,可能没有蛋炒饭那么香。到底是蛋炒饭好还是盖浇饭好呢?其实这类问题都很难回答,非要比个上下高低的话,就必须设定一个场景,否则只能说是各有所长。如果大家都不是美食家,没那么多讲究,那么从饭馆角度来讲的话,做盖浇饭显然比蛋炒饭更有优势,他可以组合出来任意多的组合,而且不会浪费。盖浇饭的好处就是"菜"“饭"分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是"可维护性"比较好,“饭” 和"菜"的耦合度比较低。蛋炒饭将"蛋”“饭"搅和在一起,想换"蛋”"饭"中任何一种都很困难,耦合度很高,以至于"可维护性"比较差。软件工程追求的目标之一就是可维护性,可维护性主要表现在3 个方面:可理解性、可测试性和可修改性。面向对象的好处之一就是显著的改善了软件系统的可维护性。

5.1 类

在Java中,类就是“属性+方法”。类也是一种对象。

Java核心结构:

​ 接口–类--对象

--抽象化–> 接口

--实例化–> 对象

​ 所以对象也叫做“实例

5.1.1 类和对象的关系

​ 在编程语言当中要想创建对象则必须先有类,类是现实世界当中具有共同特征的事物进行抽象形成的模板或概念。而对象是实际存在的个体。

​ 例如:“汽车”就是一个类(所有的汽车都有方向盘、发动机,这是它们的共同特征),“你家的那个汽车”就是一个真实存在的对象。或者说“明星”是一个类,“刘德华”就是一个对象。“沈腾”、“赵本山”、“宋丹丹”都是实际存在的对象,他们都属于“笑星”类,类描述事物的共同特征,那么“笑星”类都有哪些共同特征呢?笑星类都有姓名、性别、年龄等状态信息(属性),他们还有一个共同的行为就是“演出”(方法)。但当具体到某个对象上之后,我们发现姓名是不同的,性别是不同的,年龄也是不同的,演出的效果也是不同的。所以我们在访问姓名、性别、年龄的时候,必须先有笑星对象,通过真实存在的笑星对象去访问他的属性,包括“演出”的时候,只有“笑星”类是不行的,必须先有笑星对象,让笑星对象去执行“演出”这个动作。

5.1.2 类的创建
[修饰符] class 类名{
   
    类体 = 属性 + 方法
}
public class Student{
   
    String name;
    int age;
    public void say(){
   
        System.out.println( name + "说话了!");
    }
}
5.1.3 类的实例化(创建对象)
public static void main(String[] args){
   
    Student s1 = new Student();
    s1.name = "张三";
    s1.age = 18;
    System.out.println( "姓名:" + s1.name + ";年龄:" + s1.age);
}

注:“s1”中保存的是一个内存地址——对象在堆内存中的地址。一旦“s1=null”且堆内存中的对象没有其他变量连接,这个对象将会被垃圾回收器回收。此时再用s1访问对象,会空指针异常

5.1.4 (内存)运行过程

创建多个对象时

5.1.5 构造方法

语法格式:

[修饰符列表] 构造方法名(形式参数列表){
   
    构造方法体;
}

① 构造方法名和类名一致。

② 构造方法用来创建对象,以及完成属性初始化操作。

③ 构造方法返回值类型不需要写,写上就报错,包括void 也不能写。

④ 构造方法的返回值类型实际上是当前类的类型。

⑤ 一个类中可以定义多个构造方法,这些构造方法构成方法重载。

⑥ 当一个类中没有提供任何构造方法,系统默认提供一个无参数的构造方法,这个无参数的构造方法叫做缺省构造器,它会把所有基本类型的实列变量设为0或false把所有引⽤类型的实例变量设为null。

⑦ 当一个类中手动提供了构造方法,那么系统将不再提供无参数的构造方法,必须手动添加一个无参构造。

5.2 封装

5.2.1 什么是封装

​ 封装可以简单理解为包装, 是指利用抽象数据类型将一系列完成某特定功能的数据和基于数据的操作包装在一起,形成一个不可分割的独立体,对外只暴露少量接口供外部调用,隐藏内部实现细节,以此来保护内部的数据以及结构安全,用术语描述就是“高内聚,低耦合”。

​ 在现实世界当中我们可以看到很多事物都是封装好的,比如“鼠标”,外部有一个壳,将内部的原件封装起来,至于鼠标内部的细节是什么,我们不需要关心,只需要知道鼠标对外提供了左键、右键、滚动滑轮这三个简单的操作。对于用户来说只要知道左键、右键、滚动滑轮都能完成什么功能就行了。为什么鼠标内部的原件要在外部包装一个“壳”呢,起码内部的原件是安全的,不是吗。再如“数码相机”,外部也有一个壳,将内部复杂的结构包装起来,对外提供简单的按键,这样每个人都可以很快的学会照相了,因为它的按键很简单,另外照相机内部精密的原件也受到了壳儿的保护,不容易坏掉。

​ 根据以上的描述,可以得出封装有什么好处呢?封装之后就形成了独立实体,独立实体可以在不同的环境中重复使用,显然封装可以降低程序的耦合度,提高程序的扩展性,以及重用性或复用性,例如“鼠标”可以在A 电脑上使用,也可以在B 电脑上使用。另外封装可以隐藏内部实现细节,站在对象外部是看不到内部复杂结构的,对外只提供了简单的安全的操作入口,所以封装之后,实体更安全了。

5.2.2 封装步骤

①需要被保护的属性使用private 进行修饰

②给这个私有的属性对外提供公开的set 和get 方法

注:set和get方法都是实例方法,不能带static。不带static的方法称为实例方法,实例方法的调用必须先new对象

5.3 继承

5.3.1 继承机制

基本作用:子类继承父类,代码可以得到复用

重要作用:有了继承才有方法的覆盖和多态

将父类所有内容复制到子类中

class 类名 extends 父类名{
   
    类体;
}
5.3.2 继承特性

父类也叫超类(superclass)基类

子类也叫**(subclass)**、派生类扩展类

java中只支持单继承,不支持多继承,而C++中支持多继承,也就是"class B extends A,C{ }"是错误的。

但java支持间接继承。

class B extends A{
   
    xxx
}class C extends B{
   
    xxx
}
  • java中规定子类继承父类,除构造方法不能继承外,剩下的都可以继承。但是私有的属性无法在子类中直接访问
  • java中的类没有显示继承任何类,则默认继承Object类,所有类都继承自Object类,都有Object类的特征
  • System.out.println(引用) 会直接输出地址。相当于System.out.println(引用.toString)
  • "toString"是object类中的一个输出对象在堆内存的地址的方法
5.3.3 方法覆盖(重写)
  • 条件一:两个类必须有继承关系
  • 条件二:重写之后的方法必须返回值类型、方法名、形式参数列表完全一致
  • 条件三:访问权限不能更低,只能更高
  • 条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少

注:方法覆盖只是和方法有关,和属性无关

5.4 多态

5.4.1 什么是多态

​ 多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

5.4.2 基础语法

向上转型

​ 子–>父 Animal a = new Cat

向下转型

​ 父–>子 Cat c = new Animal

​ 两种类型之间必须要有继承关系

多态指的是:

​ 父类型引用指向子类型对象

​ 包括编译和运行阶段

​ 编译阶段:静态绑定父类的方法

​ 运行阶段:动态绑定子类对象的方法

​ 多种形态

5.4.3 instanceof运算符

instanceof 可在运行阶段动态判断引用指向的对象类型

语法:

// 引用 instanceof 类型
// 例如
d instanceof Cat    // 该表达式输出结果为ture或false

Java规范:任何情况下使用向下转型时,一定要使用instanceof 运算符进行判断,避免类型转换异常

5.5 this和super

  • this

    this是一个变量,是一个引用。this保存当前对象的内存地址,指向自身。this储存在堆内存当中的对象内部。

    this只能使用在实例方法中,谁调用这个方法,this就是谁。

    使实例方法中的局部变量有意义化,把变量指向对象,可读性高。

    构造方法也可使用this指向对象

    this(实参) 只能出现在构造方法的第一行,例如:

//当new一个无参对象时,this语法将实例变量赋值为(year=1970,month=1,day=1)减少代码量
public Date(){
   
    /*
    this.year = 1970;
    this.month = 1;
    this.day = 1;
    */
    this(1970,1,1);
}
public Date(int year, int month, int day){
   
    this.year = year;
    this.month = month;
    this.day = day;
}
  • super

    严格来说,super 其实并不是一个引用,它只是一个关键字,super 代表了当前对象中从父类继承过来的那部分特征。this 指向一个独立的对象,super 并不是指向某个“独立”的对象,假设张大明是父亲,张小明是儿子,有这样一句话:大家都说张小明的眼睛、鼻子和父亲的很像。那么也就是说儿子继承了父亲的眼睛和鼻子特征,那么眼睛和鼻子肯定最终还是长在儿子的身上。假设this指向张小明,那么super 就代表张小明身上的眼睛和鼻子。换句话说super 其实是this 的一部分。如下图所示:张大明和张小明其实是两个独立的对象,两个对象内存方面没有联系,super 只是代表张小明对象身上的眼睛和鼻子,因为这个是从父类中继承过来的,在内存方面使用了super 关键字进行了标记,对于下图来说“this.眼睛”和“super.眼睛”都是访问的同一块内存空间。

    语法:

    • super. super()
  • super. 访问父类特征时,若子类也有相同特征,super. 不能省,省了会访问子类的该特征

    • super() 作用:调用父类的构造方法,代码复用
  • super() 必须在构造方法第一行,若第一行没有手动写super,系统会默认写上super()

    • super()this() 只能存在一个,this() 调用本类中的其他方法
  • 在java中调用子类构造方法时父类的构造方法一定会执行

  • this和super比较

5.6 修饰符

5.6.1 权限修饰符

5.6.2 特征修饰符
static
  • 定义:static 是java 语言中的关键字,表示“静态的”,它可以用来修饰变量、方法、代码块等,修饰的变量叫做静态变量,修饰的方法叫做静态方法,修饰的代码块叫做静态代码块

  • 成员变量分为实例变量静态变量

    实例变量是和对象相关的,访问时采用"引用. "的方式访问。需要new对象

    静态变量是和类相关的,访问时采用"类名. "的方式访问。不需要new对象

    静态变量保存在方法区

  • 实例方法静态方法

    实例方法和对象相关,访问时用"引用.方法"。需要new对象

    静态方法和类相关,访问时用"类名.方法"。不需要new对象

  • 静态代码块

//静态代码块在类加载时执行,并且只执行一次。
//在main方法执行之前执行。
//静态代码块按照自上而下顺序执行。
static {
   
    java语句;
    java语句;
}
  • 实例代码块
//创建对象之后调用构造方法之前执行
{
   
    java语句;
    java语句;
}
final
  • final表示最终的,不可变的
  • final可修饰变量、方法、类等
  • final修饰的类无法被继承
  • final修饰的方法无法被覆盖
  • final修饰的局部变量只能赋一次值
  • final修饰的引用永远只能指向一个对象
  • final修饰的实例变量必须手动赋值,且只能赋一次值
  • static final修饰的静态变量,称为常量,常量名全部大写,单词之间下划线隔开
  • 常量和静态变量都储存在方法区,常量只能赋值一次
abstract(抽象类)
  • Java中用abstract关键字标记的类就是抽象类

  • 语法:

[修饰符列表] abstract class 类名{
   
    类体;
}
  • 抽象类:类与类之间有共同特征,将这些具有共同特征的类进一步抽象形成了抽象类。类本身是不存在的,所以抽象类无法创建对象
  • 抽象类是用来被继承的
  • final和abstract无法同时存在
  • 抽象类的子类也可以是抽象类
  • 抽象方法没有方法体
  • 抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
  • 一个非抽象的类继承抽象类,必须把抽象类中的抽象方法实现
  • 抽象方法的实现也就是方法重写(覆盖)
interface(接口)
  • Java中被interface声明的是接口

  • 语法:[修饰符列表] interface 接口名{ }

  • 接口我们可以看作是抽象类的一种特殊情况,在接口中只能定义抽象的方法和常量

    1)接口中的方法默认都是public abstract 的,不能更改\

    2)接口中的变量默认都是public static final 类型的,不能更改,所以必须显示的初始化

    3)接口不能被实例化,接口中没有构造函数的概念

    4)接口之间可以继承,但接口之间不能实现

    5)接口中的方法只能通过类来实现,通过implements 关键字

    6)如果一个类实现了接口,那么接口中所有的方法必须实现

    7)一类可以实现多个接口

    8)继承和实现可以共存,extends在前implements在后

  • 接口和抽象类的区别

    a)接口描述了方法的特征,不给出实现,一方面解决java 的单继承问题,实现了强大的可接插性

    b)抽象类提供了部分实现,抽象类是不能实例化的,抽象类的存在主要是可以把公共的代码移植到抽象类中

    c)面向接口编程,而不要面向具体编程(面向抽象编程,而不要面向具体编程)

    d)优先选择接口(因为继承抽象类后,此类将无法再继承,所以会丧失此类的灵活性)

5.7 Object类

Object类是所有Java的根类,如果声明类时为使用extends关键字指明其基类,则默认Object为基类

5.7.1 toString()

作用:默认情况下返回一个“以文本方式表示”此对象的字符串

通常情况下会把toString()重写

5.7.2 equals()

“==”equals()的区别:

​ 双等号可以比较基本类型和引用类型,等号比较的是值,特别是比较引用类型,比较的是引用的内存地址

​ 采用equals 比较两个对象是否相等,通常会对equals方法重写,自定义比较规则

5.7.3 finalize

垃圾回收器(Garbage Collection),也叫GC,垃圾回收器主要有以下特点:

1)当对象不再被程序使用时,垃圾回收器将会将其回收

2)垃圾回收是在后台运行的,我们无法命令垃圾回收器马上回收资源,但是我们可以告诉他,尽快回收资源【System.gcRuntime.getRuntime().gc()

3)垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize 方法

4)GC 主要针对堆内存

5)单例模式的缺点

5.8 包和import

5.8.1 package

package出现在java源文件第一行

//package 域名倒叙 + 项目名 + 模块名 + 功能名
//例如
package com.aaa.bbb.ccc;

完整类名 = 包名 + 类名

5.8.2 import

调用java.lang和同包下的类不需要import,其他情况都需要import导包

语法:import 完整包名;import 包名.*;

import在package之后,class之前

5.8.3 JDK常用包

java.lang,此包Java 语言标准包,使用此包中的内容无需import 引入

java.sql,提供了JDBC 接口类

java.util,提供了常用工具类j

ava.io,提供了各种输入输出流

5.9 内部类

  • 内部类分为四种:

    实例内部类

    静态内部类

    局部内部类

    匿名内部类

  • 实例内部类:

    创建实例内部类,外部类的实例必须已经创建

    实例内部类会持有外部类的引用

    实例内部不能定义static 成员,只能定义实例成员

  • 静态内部类:

    静态内部类不会持有外部的类的引用,创建时可以不用创建外部类

    静态内部类可以访问外部的静态变量,如果访问外部类的成员变量必须通过外部类的实例访问

  • 局部内部类:

    局部内部类是在方法中定义的,它只能在当前方法中使用。和局部变量的作用一样局部内部类和实例内部类一致,不能包含静态成员

  • 匿名内部类:

    MyInterface myInterface = new MyInterface() {
         
        public void add() {
         
            System.out.println("-------add------");
        }
    };
    

第六章 数组

6.1 数组简介

  • 定义:数组是指一组数据的集合,数组中的每个数据称为元素。数组中的元素可以是任意类型(基本类型和引用类型),同一个数组里只能存放类型相同的元素

  • 一维数组

    动态初始化:int[] arr = new int[5];

    静态初始化:int[] arr = {1,2,3};

  • 二维数组

    动态初始化:int[][] arr = new int[2][3];

    静态初始化:int[][] arr = { {1,2,3},{1,2},{6,5}};

  • 数组内存层面

其中data变量储存的是下标为[0]的元素的内存地址,整个数组的元素内存地址是连续的。

当数组是引用数据类型时:

二维数组的内存结构:

其中1,2,3 在内存中分别是三块不同的内存

6.1.1 数组扩容
  • Java中数组长度一旦确定则不可变。

  • 数组的扩容:

    实际是创建一个新的大容量数组,将小容量数组的数据拷贝到新数组。

  • 结论:数组的扩容因为涉及到拷贝问题,扩容效率较低,在实际开发中应尽量避免数组扩容。

6.2 数组常用算法

6.2.1 冒泡排序

案例:假设有5 个数字3,1,6,2,5 在一个int 数组中,要求按从小到大排序输出

冒泡排序的算法是这样的,首先从数组的最左边开始,取出第0 号位置(左边)的数据和第1号位置(右边)的数据,如果左边的数据大于右边的数据,则进行交换,否而不进行交换。接下来右移一个位置,取出第1 个位置的数据和第2 个位置的数据,进行比较,如果左边的数据大于右边的数据,则进行交换,否而不进行交换。沿着这个算法一直排序下去,最大的数就会冒出水面,这就是冒泡排序。

以上示例排序过程如下:

从上面我们看到了比较了N-1 次,那么第二遍就为N-2 次比较了,如此类推,比较次数的公式如下:

(N-1) + (N-2)+...+1=((N-1)*N)/2

所以以上总共比较次数为 ((5-1)*5)/2=10

public class ArraySortTest01 {
   
    public static void main(String[] args) {
   
        int[] data = {
   3,1,6,2,5};
        for (int i=data.length-1; i>0; i--) {
   
            for (int j=0; j<i; j++) {
   
                if (data[j] > data[j+1]) {
   
                    int temp = data[j];
                    data[j] = data[j+1];
                    data[j+1] = temp;
                }
            }
        }
        for (int i=0; i<data.length; i++) {
   
            System.out.println(data[i]);
        }
    }
}
6.2.2 选择排序

选择排序对冒泡排序进行了改进,使交换次数减少,但比较次数仍然没有减少。

案例:假设有5 个数字3,1,6,2,5 在一个int 数组中,要求按从小到大排序输出

采用选择排序,选择排序是这样的,先从左端开始,找到下标为0 的元素,然后和后面的元素依次比较,如果找到了比下标0 小的元素,那么再使用此元素,再接着依次比较,直到比较完成所有的元素,最后把最小的和第0 个位置交换。

以上示例排序过程如下:

第二遍排序将从下标为1 的元素开始,以此类推,经过N(N-1)/2 次比较,经过N 次数据交互就完成了所有元素的排序。

public class ArraySortTest02 {
   
    public static void main(String[] args) {
   
        int[] data = {
   3,1,6,2,5};
        for (int i=0; i<data.length; i++) {
   
            int min = i;
            for (int j=i+1; j<data.length; j++) {
   
                if (data[j] < data[min]) {
   
                    min = j;
                }
            }
            //进行位置的交换
            if (min != i) {
   
                int temp = data[i];
                data[i] = data[min];
                data[min] = temp;
            }
        }
        for (int i=0; i<data.length; i++) {
   
            System.out.println(data[i]);
        }
    }
}
6.2.3 数组二分法查找

查找数组中的元素我们可以遍历数组中的所有元素,这种方式称为线性查找。线性查找适合与小型数组,大型数组效率太低。如果一个数组已经排好序,那么我们可以采用效率比较高的二分查找或叫折半查找算法

假设,我们准备采用二分法取得18 在数组中的位置

第一步,首先取得数组0~9 的中间元素

​ 中间元素的位置为:(开始下标0 + 结束下标9)/2=下标4

​ 通过下标4 取得对应的值15

​ 18 大于15,那么我们在后半部分查找

第二步,取数组4~9 的中间元素

​ 4~9 的中间元素=(下标4 + 1 +下标9)/2=下标7

​ 下标7 的值为18,查找完毕,将下标7 返回即可

以上就是二分或折半查找法,此种方法必须保证数组事先是排好序的,这一点一定要注意

6.4 Arrays工具类

6.4.1 Arrays.length 数组长度
public static void returnArrayLength() {
   
    int[] numGroup = {
   25,12,68,78,33,55};
    System.out.println("输出数组长度为:" + numGroup.length);
}
6.4.2 Arrays.sort 数组排序(小到大)
public static void returnArraysSort() {
   
	int[] numGroup = {
   25,12,68,78,33,55};
	Arrays.sort(numGroup);
	for (int i : numGroup) {
   
		System.out.print(i+"\t");
	}
}
6.4.3 Arrays.binarySerch() 二分查找
public static void returnArraysBinarySerch() {
   
    int[] numGroup = {
   25,12,68,78,33,55};
    int index=Arrays.binarySearch(numGroup, 12);
    System.out.println("该元素下标为:"+index);
}
6.4.4 Arrays.toString() 数组的打印
public static void returnArrayToString() {
   
    int[] numGroup = {
   25,12,68,78,33,55};
    System.out.println("输出数组内容为:" + Arrays.toString(numGroup) );
}
6.4.5 Arrays.fill() 数组的填充
public static void returnArrayFill() {
   
    int[] numGroup = {
   25,12,68,78,33,55};
    Arrays.fill(numGroup, 13);
    System.out.println("数组的填充:"+Arrays.toString(numGroup));
}
6.4.6 Arrays.equals() 判断两个数组大小是否相等
public static void returnArraysEquals() {
   
    int[] numGroup = {
   25,12,68,78,33,55};
    int[] numGroup02 = {
   35,12,68,78,33,55};
    Boolean judge=Arrays.equals(numGroup, numGroup02);
    System.out.println("判断两个数组是否相等:"+judge);
}
6.4.7 Arrays.copyOf() 数组的拷贝
public static void returnArrayListCopyOf() {
   
	int[] numGroup = {
   25,12,68,78,33,55};
	int[] numGroup02=null;
	numGroup02=Arrays.copyOf(numGroup, 9);    //从下标0开始拷贝9个元素
	System.out.println(Arrays.toString(numGroup02));
}

第七章 常用类

7.1 String

7.1.1 String 特点

字符串不可变,它们的值在创建之后不能被更改;虽然String的值是不可变的,但是它们可以被共享

字符串的效果上相当于字符数组(char[]),但是底层原理是字节数组(byte[])

通过new创建的字符串对象,每一次new都会申请一块内存空间,虽然内容是相同的,但是地址值是不同的

以""方式给出的字符串,只要字符序列相同(顺序和大小写完全相同),无论在程序代码中出现几次,JVM都只会创建一个String对象放置于堆内存的字符串常量池中

7.1.2 String 常用方法
//返回字符串指定索引的char字符
char charAt(int index);

//判断字符串是否以指定的后缀结束
boolean endsWith(String suffix);
//判断字符串是否以指定的前缀开始
boolean startsWith(String prefix);
//判断字符串从指定的索引开始,是否以指定的前缀开始
boolean startsWith(String prefix, int toffset);

//字符串相等比较,不忽略大小写
boolean equals(Object anObject);
//字符串相等比较,忽略大小写
boolean equalsIgnoreCase(String anotherString);

//取得指定字符在字符串的位置
int indexOf(String str);
int indexOf(String str, int fromIndex);
//返回最后一次字符串出现的位置
int lastIndexOf(String str);
int lastIndexOf(String str, int fromIndex);

//取得字符串的长度
int length();

//判断是否为空字符串
boolean isEmpty();

//判断前面的字符串是否包含后面的子字符串
boolean contains(CharSequence s);

//替换字符串中指定的内容
String replace(char oldChar, char newChar);
String replaceAll(String regex, String replacement);

//根据指定的表达式拆分字符串
String[] split(String regex);
String[] split(String regex, int limit);

//截子串
String substring(int beginIndex, int endIndex);

//去前尾空格
String trim();

//将其他类型转换成字符串
static String valueOf(E e);

//将字符串转换成小写
String toLowerCase();
//将字符串转换成大写
String toUpperCase();
  • “==”与“equals”的区别

    ==:进行的是数值比较,比较的是两个字符串对象的内存地址数值。

    equals():可以进行字符串内容的比较。

7.2 StringBuffer 和 StringBuilder

  • StringBuffer

    StringBuffer 称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer 是可变对象,这个是String 最大的不同。

    //创建一个初始化容量为16个byte[] 数组。(字符串缓冲区对象)
    StringBuffer stringBuffer = new StringBuffer();
    //拼接字符串,append() 追加方法
    stringBuffer.append("a");
    stringBuffer.append(3.14);
    
  • StringBuilder

    用法同StringBuffer,StringBuilder 和StringBuffer 的区别是StringBuffer 中所有的方法都是同步的,是线程安全的,但速度慢,StringBuilder 的速度快,但不是线程安全的。

  • “+”连接符

    Java语言为“+”连接符以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象。

    public static void main(String[] args) {
         
        int i = 10;
        String s = "abc";
        System.out.println(s + i);
    }
    

    底层实现原理:使用“+”拼接字符串时会创建一个StringBuilder()对象,并调用append()方法将数据拼接,最后调用toString()方法返回拼接好的字符串。

7.3 包装类

<

本文标签: 字数笔记全文JavaSE