Java 基础概述
- Java 具有面向对象、跨平台、健壮性等特点,按照应用范围分为三个版本:JavaSE、JavaEE、JavaME;
- JavaSE 的结构组成:
- JDK:Java 开饭环境的核心组件,提供编译、调试以及运行 Java 程序的所有工具;
- JRE:Java 运行时环境,是 JVM 的实现,提供了运行 Java 程序的平台。JRE 包含 JVM,但不包含 Java 编译器、调试器等开发工具;
- JVM:程序运行时,JVM 负责执行指令,管理数据、内存、寄存器,JVM 屏蔽了底层运行平台的差异,实现了“一次编译,到处运行”;
Java 基础语法
关键字
- 定义:被 Java 语言赋予了特殊含义,存在专门用途的字符串。
- 特点:关键字中所有的字母均为小写。
- 示例以及分类:
- 数据类型关键字:
byte\short\int\long\float\double\boolean\char
- 流程控制关键字:
if\else\switch\case\default\while\do\break\continue\return
- 类、方法、实例、变量关键字:
private\protected\public\void\abstract\final\static\synchronized\extends\implements\new\this\super\instanceof
- 异常处理关键字:
try\catch\finally\throw\throws
- 用于包的关键字:
package\import
- 其他修饰符关键字:
native\strictfp\transient\volatile\assert
- 数字类型值的字面值:
true\fall\null
- 保留字:
goto\const
标识符
Java 对于各种变量、方法、类等要素命名时使用的字符序列均称为标识符,即需要自己命名的地方都称为标识符。
标识符的合法规则
- 由 a-z、A-Z、0-9、_、$ 组成;
- 严格区分大小写,长度无限制;
- 不可以以数字开头;
- 不可以使用关键字和保留字,但是可以包含关键字和保留字;
- 不能包含空格;
名称命名规范
- 包名:多单词组成时所有字母小写:
xxxyyyzzz
- 类名、接口名:多单子组成时所有单侧的首字母大写:
XxxYyyZzz
- 变量名、方法名:多单词组成时,第一个单词的首字母小写,后续单词的首字母大写:
xxxYyyZzz
- 常量名:所有字母大写。多单词组成时每个单词之间使用下划线分割:
AAAA\XXX_YYY_ZZZ
变量与常量
变量
- 变量的概念
- 变量时内存中的一个存储单元,该区域的数据可以在同一类型范围内不断的变化;
- 变量时程序中最基本的存储单元,其包含变量类型、变量名以及存储的值;
- 变量的分类
- 成员变量
- 类变量:方法之外的变量,以
static
修饰; - 实例变量:方法之内的变量,不以
static
修饰;
- 局部变量:类的方法或者代码块中的变量;
常量
- 一种特殊的变量,其值在被设定后,在程序的运行过程当中不允许改变;
- 常量的声明:
final <数据类型> <变量名> = <初始化值>;
,例如final double PI = 3.14;
数据类型
Java 是一种强类型语言,每个变量都必须声明类型。
数据类型的分类
- 数据类型
- 基本数据类型
- 数值类型
- 整数类型(
byte\short\int\long
) - 浮点类型(
float\double
) - 字符类型(
char
)
- 布尔类型(
boolean
)
- 引用数据类型
- 类(
class
)(String
类型是一个类,属于引用数据类型) - 接口(
interface
) - 数组(
[]
)
基本数据类型
类型 | 存储空间 | 取值范围 | 默认值 | 包装类 |
---|
byte | 1字节 | -128~127 | (byte)0 | Byte |
short | 2字节 | -32786~32767 | (short)0 | Short |
int | 4字节 | -2的31次方~+2的31次方减1 | 0 | Integer |
long | 8字节 | -2的63次方~+2的63次方减1 | 0L | Long |
float | 4字节 | 3.4e-45~1.4e38 | 0.0F | Float |
double | 8字节 | 4.9e-324~1.8e308 | 0.0 | Double |
char | 2字节 | unicode 字符,使用单引号括起来 | ‘\u0000’ | Character |
boolean | 1字节 | true\false | false | Boolean |
基本数据类型的转换
- 自动类型转换
- 容量小的数据类型可以自动转换为容量大的数据类型;
byte\short\char --> int --> long -->float --> double
,int\long
转换为float\double
可能会出现数据丢失的问题;
- 运算
- 多种数据类型参与运算时,系统首先自动将所有数据类型转换为容量最大的那种数据类型,然后再进行运算;
byte\short\char
三者是平级的,因此不能相互转换,他们三者在进行运算时首先转换为int
类型;boolean
类型不能与其他数据类型进行运算;- 当任何基本数据类型与字符串
String
进行连接运算+
时,基本数据类型将自动转化为String
类型;
运算符
运算符 | 种类 |
---|
算术运算符 | +, -, *, /, %, ++, -- |
赋值运算符 | =, +=, -=, *=, /= |
关系运算符 | >, <, >=, <=, ==, !=, instanceof |
逻辑运算符 | &, |, !, ^, &&, ||, ! |
三元运算符 | 条件 ? 执行语句1 : 执行语句2 |
位运算符 | &, |, ^, ~, >>, >>, >>> |
instanceof
:是否为某类的对象,"hello" instanceof String; // true
- 逻辑运算符用于连接布尔类型表达式
&
和&&
的区别:前者左右表达式均需要运算;后者中若左边表达式为假,则右侧表达式不参与运算|
和||
的区别:前者左右表达式均需要计算;后这种若左边表达式为真,则右侧表达式不参与计算^
异或:左右表达式相同时为 false,不同时为true
- 位运算符:应用于
byte\short\int\long\char
等类型,位运算符作用在所有位上,并且按位进行运算
流程控制
- 顺序结构
- 分支结构
- 根据条件选择性的执行某段代码
if..else
和switch..case..
两种分支语句switch..case
语句的注意事项:
- switch 表达式的值只能为以下几种数据类型:
byte\short\int\char\Enum\String
; - case 子句中的值必须为常量,不能是变量或者不确定的值;
break
用于在执行完一个 case 分支后跳出,若没有 break 程序会顺序执行到 switch 代码块尾部;default
子句是可以任选的,当没有匹配到 case 时,执行 default。default 位置任意,但建议放在最后;
- 循环结构
- 根据循环条件,重复性的执行某段代码
while
、do...while
、for
三种循环语句
for
循环的初始化部分可以声明多个变量,但必须是同一个类型,使用逗号分隔,循环条件处可以有多个变量更新,逗号分隔;while
循环中不要忘记条件的迭代部分,否则陷入死循环;do..while
循环至少执行一次循环体;
- JDK 1.5 提供了
foreach
循环,便于遍历集合、数组元素
break 与 continue
break
用于终止某个代码块的执行,只能用于switch
和循环语句当中;continue
用于跳过一次循环体的执行,进入下一次循环,故只能用在循环体当中;- 可以通过带标签的
break label\continue label
来指定对哪一层循环进行操作;
数组
数组概述
- 定义:数组时多个相同类型的数据按照一定顺序排列的集合;
- 特点:
- 数组本身为引用数据类型,但其中的元素可以是任何数据类型;
- 数组的长度一旦确定,不能再修改;
- 数组中的数据称为元素,每个元素都可以通过下标直接访问;
- 创建数组对象会在内存当中开辟一段连续的空间,数组名中引用的就是这块连续空间的首地址,数组对象本身是在堆中存储的;
Java 内存的几个概念
- 堆(heap)
- 存放 new 的对象实例或者数组,所有线程共享;
- 实例变量(即成员变量)与对象关联在一起,故也在堆中存储;
- 对象不再被使用时,会在不确定的时间被垃圾回收器回收;
- 栈(stack)
- 存放局部变量(基本数据类型–值、引用数据类型–对象在堆中的地址),是线程的私有区域;
- 数据用完时所占空间自动释放;
- 方法区(Method Area)
- 存储被 java 虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等,所有线程共享;
数组的声明与初始化
- 声明方式
int[] a
或者int a[]
- 多维数组:
int a[][]
或int[][] a
- 初始化
- 静态初始化:定义数组的同时为数组元素分配空间并赋值;
- 动态初始化:数组声明和为元素分配空间的操作与赋值操作分开进行;
- 默认初始化:数组一旦被分配空间,其内部的元素也将根据类型被初始化;
数组的使用
- 遍历:可以使用基本循环(
for\while\do..while..
)或增强for循环
遍历; - 数组工具类
Arrays
Arrays.toString
:数组转字符串Arrays.sort
:数组排序Arrays.binarySearch
:二分查找(使用二分查找需要先将数组排序)Arrays.fill
:元素填充Arrays.asList
:转换为 List 集合Arrays.equals
:数组比较Arrays.copyOf
:数组复制
面向对象
类与对象
- 类是对一类事物的描述,是抽象的、概念上的定义;
- 类的访问机制:
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量(例外:
static
的方法不能访问非static
的成员变量); - 不同类中的访问机制:先创建要访问的类的对象,在通过对象访问类中定义的成员;
- 对象是实际存在的某一类事物的单独个体,因此也成为实例(instance);
- 创建:
类名 对象名 = new 类名;
- 使用
对象名.对象成员
的方式可以访问对象成员,包括属性和方法; - 对象内存分析:一个实例化后的对象,会在堆中被分配内存,并将这个堆地址存放在栈中相应的变量处;
类的成员变量与局部变量
| 成员变量 | 局部变量 |
---|
声明位置 | 直接声明在类中 | 在方法形参或内部、代码块、构造器内声明 |
修饰符 | private/public/static/final | 不能用权限修饰符修饰,可以用final 修饰 |
初始化值 | 有默认的初始化值 | 无默认初始化值,除形参外必须显式的进行初始化 |
内存位置 | 堆内存(非static )或方法区(static ) | 栈内存 |
类的方法
- 方法的重载
- 在一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可,与返回值无关;
- 示例:
int add(int x, int y)
int add(int x, int y, int z)
double add(double x, double y)
- 可变个数的形参
- 声明格式:
方法名(参数的类型... 参数名)
; - 可变形参一般放在最后声明;
- 一个方法最多只能声明一个可变形参;
- 可变形参与使用数组一致;
- 方法参数的传递
- Java 中方法参数的传递只有一种方式:值传递,即实际传入的是参数值的副本,参数本身不受影响;
- 对于基本数据类型:变量的“数据值”传递给形参;
- 对于引用数据类型:变量的“地址值”传递给形参;
类的构造器
- 特征
- 与类的名字相同;
- 不声明返回值的类型;
- 不能被
static\final\synchronized\abstract\native
修饰;
- 作用
- 使用
new
创建对象时必须使用类的构造器; - 用于给类中的属性初始化赋值;
- 分类
- 隐式无参构造器(系统默认提供);
- 也可以显式的定义一个或者多个构造器(有参、无参);
- 注意
- 每个类都至少有一个构造器;
- 默认构造器的修饰符与所属类的修饰符一致;
- 一旦显式的定义了构造器,系统则不在提供默认的构造器;
- 父类的构造器不能被子类继承;
- 一个类可以创建多个重载的构造器;
面向对象
面向对象:封装
- 隐藏对象内部的复杂性,只对外公开简单的接口
- 目的:为了限制不合理的操作
权限修饰符
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
---|
private | √ | | | |
缺省 | √ | √ | | |
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
- class 的权限只有
public
和default(缺省)
- 上述四种都可以用来定义类成员的访问权限
面向对象:继承
- 特征:若多个类中存在相同的属性和行为,那么可以将这些内容单独抽取到一个类当中,其他的类继承这个类即可
- 作用
- 降低代码冗余度,提高代码复用性
- 有利于功能的扩展
- 类与类之间产生了关系,提供了多态的前提
- 规则
- 子类继承父类,就继承了父类非
private
的属性和方法,子类是父类的扩展 - 类与类之间是单继承的,接口是多继承的
继承–重写
- 定义:在子类中可以对从父类继承的方法进行改造,程序执行时子类的方法将覆盖父类的方法
- 注意
- 重写的方法必须与父类被重写方法拥有相同的方法名称、参数列表
- 重写的方法的返回值类型不能大于父类被重写方法的返回值类型
- 重写的方法的访问权限不能小于父类被重写方法的访问权限
- 父类的静态方法不能被子类重写为非静态方法;父类的非静态方法也不能被子类重写为静态方法(两种情况都将编译出错)
- 私有方法不能被子类重写
继承–super关键字
使用super
关键字可以访问或者调用父类中的属性、方法、构造器,其追溯不仅限于直接父类。
super
与this
的区别:
区别点 | super | this |
---|
访问属性 | 直接访问父类中的属性 | 访问本类中的属性,若本类中无此属性则从父类中继续查找 |
调用方法 | 直接访问父类中的方法 | 访问本类中的方法,若本类中无此方法则从父类中继续查找 |
调用构造器 | 调用父类构造器,必须放在子类构造器的首行 | 调用本类构造器,必须放在构造器的首行 |
面向对象:多态
- 对象的多态性:父类引用指向子类对象
- Java 引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量是使用的类型决定,运行时类型由实际赋给该变量的对象决定
- 多态的作用:提高代码的通用性
- 多态的前提:要存在继承或者实现关系,需要子类重写父类的方法
对象的多态性
- 一个变量只能有一种确定的数据类型
- 一个引用类型的变量可以指向多种不同类型的对象
- 一个引用类型变量如果声明为父类的类型,但实际引用的确实子类的对象,那么该变量便不能访问子类中新添加的属性和方法
- 多态是方法的多态,属性没有多态性
instanceof 与类型转换
x instanceof Y
:检验对象 x 是否为类 Y 的对象,返回值为boolean
- 要求 x 所属的类与 Y 类必须是子类和父类的关系,否则编译错误
- 结果取决于变量 x 所指向的对象的实际类型是不是 Y 类型的子类
对象的类型转换
- 从子类向父类的类型转换自动进行
- 从父类到子类的类型转换需要强制类型转换实现
- 无继承关系的引用类型的类型转换是非法的
Object 类
Object
是所有 Java 类的根父类,未声明extend
关键字的类的父类默认为java.lang.Object
- 常用方法
public boolean equals(Object obj)
:对象比较public String toString()
:转字符串,返回类名和它的引用地址,可以根据需要重写
== 与 equals
==
- 基本数据类型比较的是数值,两个变量值相等即为 true
- 引用数据类型比较的是地址,两个变量指向同一个对象即为 true
equals
- 只能比较引用类型,未被重写的
equals
与==
作用相同,比较的是地址值 - 对于
File
、String
、Date
以及包装类
来说,比较的是类型以及内容(因为这些类重写了equals()
)
static 关键字
- 类属性和类方法
- 类属性是各个对象之间共享的变量,不因对象的不同而改变;
- 类方法与对象无关,不需要创建对象就可以调用类方法;
static
使用范围:属性、方法、代码块、内部类
static 修饰的特点
- 随着类的加载而加载,属于类本身,优先于对象存在
- 被修饰的成员被所有对象共享
- 访问权限允许时,可以不创建对象,直接通过类调用
- 静态变量在内存中只有一份,被所有实例共享
this
和super
无法在静态方法中使用;静态方法不能被重写;静态方法与非静态方法不能互相访问(加载顺序不同)
代码块
- 作用:一般用于堆 Java 对象或者类进行初始化
- 静态代码块
- 可以对类的属性、类的声明进行初始化操作,可以有输出语句
- 不可以调用非静态的方法
- 若有多个静态代码块,则按照从上往下顺序执行,执行优先于非静态代码块
- 静态代码块随着类的加载而加载,且只执行一次
- 非静态代码块
- 可以对类的属性、类的声明进行初始化操作,可以有输出语句
- 可以调用非静态的结构,还可以调用静态的变量或者方法
- 若有多个非静态代码块,则按照从上往下顺序执行
- 每次创建对象的时候,都会执行一次,且先于构造器执行
final 关键字
final
修饰类:表示该类不可被继承final
修饰方法:表示该方法不能被子类重写final
修饰变量:表示为常量,该量只能被赋值一次,且必须在声明/在每个构造器中/代码块中显示的赋值才能使用
抽象类与抽象方法
- 抽象类:将一个父类设计得非常抽象以至于没有具体的实例,称为抽象类,使用
abstract
关键字修饰 - 抽象方法:只有方法的声明,没有方法的实现,且以分号结束,称为抽象方法,使用
abstract
关键字修饰 - 关系:抽象类中可以没有抽象方法;有抽象方法的类一定要声明为抽象类
- 特点:
- 抽象类不能被实例化,抽象类是用来被继承的
- 抽象类的子类必须实现抽象方法,若没有重写全部的抽象方法,该子类仍然为抽象类
- 不能使用
abstract
修饰变量、代码块、构造器 - 不能使用
abstract
修饰私有方法、静态方法、final
的方法、final
的类
接口
- 定义:接口是抽象方法和常量值定义的集合,接口是一种规范,定义的是一组行为准则,使用
interface
修饰 - 特点:
- 接口中没有构造器
- 接口中的所有成员变量默认使用
public static final
修饰 - 接口中的所有抽象方法默认使用
static abstract
修饰 - 接口采用多继承机制,实现接口的类必须实现接口中的所有方法
- 接口用于被实现类实现,其与实现类之间存在多态性
- 改进:Java 8 为接口添加了静态方法和默认方法
接口和抽象类的对比
区别点 | 抽象类 | 接口 |
---|
定义 | 包含抽象方法的类 | 抽象方法和全局常量的集合 |
组成 | 构造方法、抽象方法、普通方法、常量、变量 | 常量、抽象方法;(1.8 新增)默认方法、静态方法 |
使用 | 子类继承抽象类extend | 子类实现接口interface |
关系 | 抽象类可以实现多个接口 | 接口不能继承抽象类,但允许继承多接口 |
常见设计模式 | 模板方法 | 工厂模式、代理模式 |
对象 | 通过对象的多态性产生实例化对象 | 通过对象的多态性产生实例化对象 |
局限 | 单继承 | |
本质 | 模板 | 行为规范 |
选择 | | 优先使用接口以避免单继承 |
内部类
- 内部类
- Java 中允许在一个类的内部定义另一个类,前者称外部类,后者为内部类
- 内部类一般定义在他的类或者语句块之内,在外部引用是必须给出完整的名称
- 分类
- 成员内部类:可以调用外部类的结构
- 静态内部类:
static
修饰 - 局部内部类:在一个方法内部声明一个类,可以调用外部类的结构
- 匿名内部类:不需要定义,需要使用的时候临时实现内部类,随之使用