JavaSE 学习

《阿里巴巴Java开发手册(终极版)》.pdf

jdk api 1.8_google.CHM

基础知识

Java三大版本

Write Once,Run Anywhere

JavaSE:标准版(桌面程序,控制台开发……)

JavaME:嵌入式开发(手机,小家电……)

JavaEE:E企业级开发 (web端,服务器开发…)

JDK&JRE&JVM

JDK: Java Development Kit
JRE: Java Runtime Environment
JVM: JAVA Virtual Machine

HelloWorld

新建一个Java文件,写入代码

在本目录下打开cmd编译Java文件,编译后出现.class文件

运行:

Java程序运行机制

编译型:所有的一次性“翻译”;

解释型:实时”翻译“;

Java既有编译也有解释:

Java基础语法

《阿里巴巴Java开发手册(终极版)》

1、注释&标识符&关键字

注释:

单行注释:\\

多行注释:\* *\

JavaDoc:文档注释:\** *\

标识符:

Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。

  • 标识符开头:字母(A-Z&a-z),$,_
  • 首字符之后:字母(A-Z&a-z),$,_,数字
  • 关键字不用于变量名或方法名
  • 标识符大小写敏感

关键字:

class:

public:

static详解:

void:

interface:

2、数据类型

强类型语言:要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用。

  • 基本类型:
    • 数值类型:
      • 整数:
    * 浮点:
    * 字符:
- 布尔类型:占1位
  • 引用类型:
    • 类
    • 接口
    • 数组

拓展:

3、类型转换

低 ————————————————-> 高

byte,short,char -> int -> long -> float -> double

  • 运算中,不同类型的数据先转化为同一类型,然后进行运算。

强制转换 高->低 (类型)变量名
自动转换 低->高

注意点:

  1. 不能对布尔值转换
  2. 不能把对象类型转换为不相干的东西
  3. 高->低:强制转换
  4. 转换时存在内存溢出、精度问题

4、变量&常量

常量:

一般用大写字母

变量的命名规范

  • 所有变量、方法、类名:见名知意
  • 类成员变量:首字母小写和驼峰原则:monthSalary
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:runO,runRun0

5、运算符

Java语言支持如下运算符:

逻辑运算符:

自增自减:

幂运算:

位运算:

三元运算符:

6、包机制

包:本质就是文件夹

  • 命名:一般利用公司域名倒置作为包名:com.kuangstudy.www
  • 语法:package pkg1[.pkg2[.pkg3...]];
  • 导包:import package1[.package2...].(className|*);
    • 导入这个包下所有的类:import com.kuang.base.*;

包机制规则:

参考:https://www.cnpanda.net/codeaudit/588.html

如上图所示,在 Java 中,会有各种各样的包,大致规则如下:

  • indi :

个体项目,指个人发起,但非自己独自完成的项目,可公开或私有项目,copyright主要属于发起者。

包名为indi.发起者名.项目名.模块名.……

  • pers:

个人项目,指个人发起,独自完成,可分享的项目,copyright主要属于个人。

包名为pers.个人名.项目名.模块名.……

  • priv:

私有项目,指个人发起,独自完成,非公开的私人使用的项目,copyright属于个人

包名为priv.个人名.项目名.模块名.……

  • onem:

与“indi”相同,推荐使用“indi”

  • team:

团队项目,指由团队发起,并由该团队开发的项目,copyright属于该团队所有

包名为team.团队名.项目名.模块名.……

  • com:

公司项目,copyright由项目发起的公司所有

包名为com.公司名.项目名.模块名.……

持久层:dao、persist、mapper

实体类:entity、model、bean、javabean、pojo

业务逻辑:service、biz

控制器:controller、servlet、action、web

过滤器:filter

异常:exception

监听器:listener

在不同的框架下一般包的命名规则不同,但大概如上,不同功能的 Java 文件放在不同的包中,根据 Java 文件的功能统一安放及命名。

7、JavaDoc

JavaSE8帮助文档

JavaDoc命令:用来生成自己的API文档

参数信息
@author作者名
@version版本号
@since指明需要最早使用的jdk版本
@param参数名
@return返回值情况
@throws异常抛出情况

使用命令行生成:

使用IDEA生成:

https://blog.csdn.net/qq_44122193/article/details/114789427

Java流程控制

1、Scanner对象

基本语法:

Scanner s = new Scanner(System.in);

  • 通过Scanner类的next)与nextLine0方法获取输入的字符串,在读取前我们一般需要使用hasNext(与hasNextLine()判断是否还有输入的数据。
  • next():
    • 1、一定要读取到有效字符后才可以结束输入。
    • 2、对输入有效字符之前遇到的空白,next())方法会自动将其去掉。
    • 3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
    • 4、next()不能得到带有空格的字符串。
  • nextLine():
    • 1、以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
    • 2、可以获得空白。

2、顺序结构

  • JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
  • 顺序结构是最简单的算法结构。
  • 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。

3、选择结构

(1)if单选择结构

(2)if双选择结构

(3)if多选择结构

(4)if嵌套结构

(5)switch多选择结构

java7开始,支持字符串比较

通过idea的反编译查看class文件

4、循环结构

(1)while循环

  • 只要布尔表达式为true,循环就会一直执行下去。
  • 我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
  • 少部分情况需要循环一直执行,比如服务器的请求响应监听等。
  • 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死奔溃!
  • 思考:计算1+2+3+…+100=?

(2)do…while 循环

While和do-While的区别:

  • while先判断后执行,do…while是先执行后判断。
  • Do..while总是保证循环体会被至少执行一次!

(3)for 循环

  • for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
  • 语法格式如下:
  • 练习1:计算0到100之间的奇数和,偶数和
  • 练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
  • 练习3:打印九九乘法表

(4)增强 for 循环(数组中重点使用)

  • Java5引入了一种主要用于数组或集合的增强型for循环。
  • Java增强for循环语法格式如下:
  • 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
  • 表达式:表达式是要访问的数组名,或者是返回值为数组的方法。

5、break continue

  • break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
  • continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。

关于goto关键字(不建议使用)

  • goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子——带标签的break和continue。
  • “标签”是指后面跟一个冒号的标识符,例如:label:
  • 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。

6、练习-打印三角形&debug

debug使用

Java方法

1、何谓方法

Java方法是语句的集合,它们在一起执行一个功能。

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用

例:System.out.println(): 调用系统类 System 中的标准输出对象 out 中的方法 println()。

System: 系统类

out: 标准输出对象

println(): 方法

设计方法的原则:就是一个方法只完成1个功能。

方法的命名规则

  • 1.方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。
  • 2.下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test<MethodUnderTest>_<state>,例如 testPop_emptyStack。

2、方法的定义及调用

方法的定义

Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

  • 修饰符:可选,定义了该方法的访问类型;
  • 返回值类型:方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
  • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。要遵守命名规则。
  • 参数类型**:**可选,参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。
    • 形参&实参
  • 方法体:方法体包含具体的语句,定义该方法的功能。

方法调用

调用方法:对象名.方法名(实参列表)

  • 当方法返回一个值的时候,方法调用通常被当做一个值。例如:int larger = max(30, 40);
  • 如果方法返回值是void,方法调用一定是一条语句。例如:System.out.println("Hello!");

3、方法重载

重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

重载规则:

  • 参数列表必须不同(参数个数、类型、参数排列顺序不一样);

  • 方法名称必须相同

  • 方法返回类型可以相同也可以不同

  • 仅仅返回类型不同不足以成为方法的重载

    ​

4、命令行传参

找对路径!

5、可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法。
  • 在方法声明中,在指定参数类型后加一个省略号(…)。
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

6、递归

递归就是:A方法调用A方法!就是自己调用自己

	利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。

递归结构包括两个部分:

  • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
    • 边界条件:
  • 递归体:什么时候需要调用自身方法。

错误案例:

StackOverflowError(栈溢出错误)

【JVM】Java内存溢出分析(堆溢出、栈溢出、方法区溢出、直接内存溢出)

int 类型最大值为 2³¹-1 (2,147,483,647)。阶乘值超过此值时会产生溢出:

12! = 479,001,600 ( < 2.1e9,安全) 13! = 6,227,020,800 ( > 2.1e9,溢出为负数)

数据类型:

  • int 最大有效 n=12
  • long 最大有效 n=20
  • BigInteger 无理论上限(但需足够堆内存)

7、练习-计算器

写一个计算器,要求实现加减乘除功能,并且能够循环接收新的数据,通过用户交互实现。

Java数组

1、数组概述

  • 数组是相同类型数据的有序集合。
  • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

2、数组声明创建

声明数组变量:

数组声明创建:

  • 获取数组长度:arrays.length
  • 数组的元素是通过索引访问的,数组索引从 0 开始。

3、内存分析

Java内存分析:

堆&栈:

数组声明时并不存在,当创建数组时才会生成,一般声明创建会一起进行

dataType[] arrayRefVar = new dataType[arraySize];

java.lang.ArrayIndexOutOfBoundsException 数组越界

4、三种初始化

  • 静态初始化
  • 动态初始化
  • 默认初始化
    • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。

5、数组的四个基本特点

  • 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
  • 其元素必须是相同类型,不允许出现混合类型。
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
  • 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

6、数组边界

  • 下标的合法区间:[0, length - 1]
  • 越界会报错:ArrayIndexOutOfBoundsException 数组下标越界异常

7、数组使用

基本使用

For-Each循环

数组作方法入参

数组作返回值

8、多维数组

多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

二维数组:

使用

9、Arrays 类

Arrays 类

JAVA JDK 1.8 API 中文文档 高清完整版 CHM

java.util.Arrays

常用功能:

  • 打印数组:toString
  • 给数组赋值:fill
  • 对数组排序:sort,升序。
  • 比较数组:equals方法比较数组中元素值是否相等。
  • 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

10、冒泡排序

时间复杂度为O(n2)

11、稀疏数组(数据结构)

当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方式是:

  • 记录数组一共有几行几列,有多少个不同值

  • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

  • 如下图:左边是原始数组,右边是稀疏数组

面向过程

1、面向过程&面向对象

  • 面向过程思想
    • 步骤清晰简单,第一步做什么,第二步做什么……
    • 面对过程适合处理一些较为简单的问题
  • 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
  • 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

面向对象

Java面向对象(基础总结)

  • 面向对象编程(Object-Oriented Programming, OOP)
  • 面向对象编程的本质:以类的方式组织代码,以对象的方式组织(封装)数据。
  • 抽象:将同一类事物中共有的特征、行为抽取出来,归纳总结
  • 三大特性:
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

类与对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是不能代表某一个具体的事物
  • 对象是抽象概念的具体实例

2、创建与初始化对象

使用 new 关键字创建对象

  • 使用new关键字创建时,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

3、构造器

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,
  • 特点:
    • 必须和类名相同
    • 必须没有返回类型,也不能写void
  • 作用:
    • new 本质在调用构造方法
    • 初始化对象的值
  • 注意点:
    • 定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造
  • alt + insert

4、创建对象内存分析

简单示意图:

5、封装

“高内聚,低耦合”

属性私有,get/set

意义:

  • 提高程序安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 系统可维护性提高

6、继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

  • **extands**的意思是“扩展”。子类是父类的扩展。

  • JAVA中类只有单继承,没有多继承!

  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

  • 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。

  • 子类和父类之间,从意义上讲应该具有”is a“的关系

  • 修饰符:

    • public
    • protected
    • default
    • private

私有属性不可继承:

Object 类

Ctrl + H:打开层次结构

在Java中,所有的类,都默认直接或间接继承 Object 类

super

super 注意点:

  • super调用父类的构造方法,必须在构造方法的第一个
  • super必须只能出现在子类的方法或构造方法
  • super 和 this 不能同时调用构造方法

对比 this:

  • 代表的对象不同:
    • this:本身调用者的对象
    • super:代表父类对象的应用
  • 前提:
    • this:没有继承也可以使用
    • super:只能在继承条件使用
  • 构造方法:
    • this():本类的构造
    • super():父类的构造

方法重写

简单理解:

子类觉得继承自父类的方法不够用或不合适,就自己重新写一个同名同参数的方法来替换它。

主要是为了实现多态,让不同类型的对象(都是父类的子类)在调用同一个方法名时,能执行各自特有的操作(Dog 叫是“汪汪”,Cat 叫是“喵喵”,但都调用 makeSound())。

想象一下:

  • 你有一个父类(比如 Animal),它定义了一个通用的方法(比如 makeSound())。
  • 然后你创建了一个子类(比如 Dog,它继承自 Animal)。
  • 在 Dog 类里,你觉得父类 Animal 的 makeSound() 方法(可能只是打印“动物发出声音”)对于狗来说不够具体。
  • 于是,你在 Dog 类中重新写了一个也叫 makeSound() 的方法,但这次让它打印“汪汪汪!”。

这个过程就叫方法重写! 子类用自己的具体实现覆盖(Override)了从父类继承来的方法实现。

  • 静态方法与非静态方法区别很大
    • 静态方法:方法的调用只和左边定义的数据类型有关
    • 非静态方法:父类的引用指向子类,子类重写了父类的方法
  • 重写需要有继承关系,子类重写父类的方法
    • 方法名必须相同
    • 参数列表必须相同
    • 修饰符:范围可以扩大但不能缩小:public>protected>default>private
    • 抛出的异常:范围,可以被缩小,不能扩大:ClassNotFoundException –> Exception(大)
  • 子类和父类必须一致:方法体不同

7、多态

多态:同一方法可以根据发送对象的不同而采用多种不同的行为方式

一个对象的实际类型是确定的,但可以指向对象的引用的类型又很多

  • 多态存在的条件:

    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 多态注意事项:

    • 多态是方法的多态,属性没有多态
    • 父类和子类,有联系;类型转换异常:ClassCastException
    • 存在条件:继承关系,方法需要重写,父类引用指向子类对象
    • 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
  • static 方法,属于类,它不属于实例

  • final 常量

  • private 方法

子类重写父类后,执行子类:

instanceof 和 类型转换 (引用类型)

instanceof:判断一个对象是什么类型

  • 父类引用指向子类的对象
  • 把子类转换为父类,向上转型
  • 把父类转换为子类,向下转型;强制转换
  • 方便方法的调用,减少重复的代码

8、抽象类

abstract

  • 不能new这个抽象类,只能靠子类去实现它;约束
  • 抽象类里可以写普通方法
  • 抽象方法必须在抽象类中
  • 抽象的抽象:约束
  • 思考:抽象类存在构造器码?

9、接口

接口:只有规范!自己无法写方法~专业的约束!约束和实现分离:面向接口编程。

接口的本质是契约。

声明类的关键字是class,声明接口的关键字是interface

作用:

  • 约束
  • 定义一些方法,让不同的人实现
  • public abstract
  • public static final
  • 接口不能被实例化,接口中没有构造方法
  • implements可以实现多个接口
  • 必须要重写接口中的方法

10、内部类

  • 一个java类中可以有多个class类,但是只能有一个public class
  • 内部类就是在一个类的内部再定义一个类,比如A类中定义了一个B类,那么B就是A的内部类,而A相对B来说就是外部类

- 成员内部类:可以操作外部类的私有属性及方法
- 静态内部类:static修饰,不能访问外部类私有属性
- 局部内部类:外部类的方法里定义的类
- 匿名内部类:没有名字初始化类

小结:

1、类与对象

类是一个模板;对象是一个具体的实例

2、方法

定义、调用

3、对象的引用

引用类型:基本类型(8)

对象是通过引用来操作的:栈 --> 堆

4、属性:字段Filed 成员变量

  • 默认初始化:
    • 数字: 0, 0.0
    • char : u0000
    • boolean : flase
    • 引用 : null
  • 修饰符 属性类型 属性名 = 属性值!

5、对象的创建和使用

  • 使用 new 关键字创建对象,构造器 Person java = new Person();
  • 对象的属性:java.name
  • 对象的方法:java.sleep()

6、类

  • 静态的属性
  • 动态的行为

异常

1、Exception&Error

  • Error
    • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
    • Java虚拟机运行错误(VirtualMachineError),当JVM不再有继续执行操作所需的内存资源
      时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终
      止;
    • 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误
      (LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
  • Exception
    • 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
      • ArrayIndexOutOfBoundsException(数组下标越界)
      • NulIPointerException(空指针异常)
      • ArithmeticException(算术异常)
      • MissingResourceException(丢失资源)
      • ClassNotFoundException(找不到类)
      • 这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
    • 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
  • Error和Exception的区别:
    • Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

2、简单分类

  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

3、异常体系结构

  • Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
  • 在JavaAPI中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。

4、异常机制

异常处理五个关键字:try catch finally throw throws

Java throw和throws 关键字

5、自定义异常

实际应用中的经验总结:

  • 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单地调用printStackTrace)去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源