这里写目录标题
JAVA SE知识图解
java简介与数据类型
java简介
java 是由 Sun Microsystems 公司于 1995 年 5 月由 James Gosling(詹姆斯。高斯林)和同事们共同研发,并在 1995 年正式推出。后来 Sun 公司被 Oracle (甲骨文)公司收购,Java 也随之成为 Oracle 公司的产品。
java的技术架构(3个)
JavaSE:标准版 桌面型引用程序
JavaEE: 企业版 服务器引用程序
JavaME:微型版 嵌入式引用程序
java语言特点
- 安全性: java提供了一些安全机制,防止一些恶意代码的攻击(安全机制,安全防范机制,安全管理机制)
- 简单性:java语言与c,c++相似但丢弃了一些难懂的操作,比如(多继承,指针等)
- 面向对象:Java 语言提供类、接口和继承等面向对象的特性
- 健壮性:java的安全检查机制是java更具有健壮性以及垃圾自动回收机制、异常处理是健壮性的重要保障
- 可移植性:跨平台操作
- 多线程:
独有的特点是:跨平台(即与平台无关性)
jdk jre jvm的区别
jvm: java可以跨平台主要依靠jvm, jvm作用是将字节码文件转化成操作系统指令.(最终是字节码在跨平台)
jre(java运行环境:如果想只允许java程序,装jre即可
jre= jvm+核心内库
jdk(java开发工具包):如果想开发一个java程序就要装jdk
jdk=开发工具+jre
区别
1、在bin文件夹下会发现,JDK有javac.exe而JRE里面没有,javac指令是用来将java文件编译成class文件的,这是开发者需要的,而用户(只需要运行的人)是不需要的。JDK还有jar.exe, javadoc.exe等等用于开发的可执行指令文件。这也证实了一个是开发环境(JDK),一个是运行环境(JRE);
2、JVM并不代表就可以执行class了,JVM执行.class还需要JRE下的lib类库的支持,尤其是rt.jar
程序的运行
- 编译: javac 类名.java
- 运行:java 类名
数据类型
基本数据类型
变量的声明在内存中开辟4个字节空间
byte short long int float double boolean char(栈内存)
byte(字节):占一个字节
short:2个字节
long 8 个字节
int 4个字节
八进制以0开头
十六进制以0x开头(不区分大小写)
float 4个字节 后要加f否则默认为double
float a = 12.12;//报错:Type mismatch: cannot convert from double to float
float a = 12.12f//不报错
double 8个字节 后面加d
double a = 12.12;//不报错
double a = 12.12d;//不报错
boolean 1个字节
char 2个字节 最大范围65534
char ch = 'a';//a
char ch1=36;//ascii码$
char ch2 =65532;//不报错 输出?代表没找到不是符号问号
char ch2 =65539;//erro:Type mismatch: cannot convert from int to char
ASCII 码(只支持英文)
Unicode(支持各个语言)
引用数据类型
类、接口、数组(堆内存)
类型转化与运算符
A类型的数据表示范围比B大,则将A类型的赋值给B类型
类型转化
自动类型转化
强制类型转化
- 会出现数据溢出
- 精度丢失
强转会出现的问题
byte a = 30;
byte b =50;
short c = a +b;//erro:Type mismatch: cannot convert from int to short
//30+50 是int类型必须要强转
short c = (short)(a+b);//正确
float a = 271273628292738437382f;
int b = (int)a;
System.out.println(b);
//b =2147483647
BigDecimal(数据较大)
运算符
常量
- 用final修饰:不可以被改变
- 广泛应用于表单验证
- 命名必须纯大写
变量:
- 内存中的一个存储区域
- 该区域有自己的名称(变量名)和类型(数据类型)
- java中每个变量都必须先声明后使用
- 该区域的数据可以在同一类型范围内不断变化
表达式
- 用算符和操作数组成
运算符
1、算数运算符
加减乘除 自增,自减 ,复合型算数运算符
自增: i++;++i
i++先做别的事,再自己加1,++i先自己加1,再做别的事情
itn x = 5
int y = (x++)+(--x)*(++x);//16
//x++ 参与运算的是5 x的值变为6
//--x 参与运算的是5 值为5
// ++x 参与运算的是6 值为6
2、赋值运算符
b=9 复合型赋值运算符 x+=100 =》x=x+100
3、关系运算符
< <= > >= = = !=
****
在引用数据类型中判断的是地址是否相等
基本数据类型中判断的是值
注* 引用数据类型和基本数据类型不能比较
4、逻辑运算符
与 && 或&
或 || 或|
非 !
5、条件运算符: 三目表达式 目:操作数
//找出两个数中最大值
int a = 49;
int b = 90;
System.out.println(a>b ? a:b);
6、位运算符
条件结构
if(条件){
}
注意:if括号里的条件是boolean类型(java中只有boolean类型能作为判断条件)
比如(如下图结果是false):
如下图(结果是false)
if-else 语句(线性睡眠)
import java.util.Arrays;
import java.util.Scanner;
public class T1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入商品价格:");
double price = sc.nextDouble();
try {
System.out.println("正在计算请等待----");
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("正在计算请等待----");
}
if(price>100) {
price = price-20;
}
System.out.println(price);
}
}
常量池 与堆内存
运算符优先级
switch
public class Three {
public static void main(String[] args) {
int num = 2;
switch (num) {
case 1:
++num;
case 2:
++num;
case 3:
++num;
default:
++num;
break;
}
System.out.println(num);
//结果是5
/*
没有break时会继续向下执行
*/
}
}
循环结构
什么时候用循环结构?
比如求1-100的累加和
while循环(先判断后执行)
语法格式
while(循环条件){
语句;
}
do-while
至少执行一次
int n=1;
do{
// 输出n的值
n++;
}while(n < 5);
注意事项:
do-while循环至少执行一次
循环条件后的分号不能丢
*补充:随机数: Math.random()*0-1;
for循环
语法格式
for(int n =1; n <=5;n++){
循环语句;
}
break语句:
跳出当前循环,break语句一旦被执行,循环体中break后面的代码将不再执行
continue:跳出本次循环
补充System.exit(0);//系统终止
-
float f1=267162711627f; float f2 = f1+1; System.out.println(f1==f2);//true会以科学计数法形式在内存中存储,小数保留7位* **BigDecimal bg1 = new BigDeecimal(F2);**
数组(引用数据类型)
string(是一个类)
为什么要使用数组
学生成绩的排序问题
概念 数组是相同类型的数据按顺序组成的一种引用数据类型
一维数组
- 声明: 在没有分配内存空间的时候叫声明
- 创建: 在分配内存空间时叫创建
- 初始化: 在填入值时叫初始化
- 元素的引用
- 长度
- 数组的应用
数组的声明
语法格式
数据类型[]数组名
数据类型 数组名【】
int[] myIntArray;
int myIntArray[];
数组创建
一、先声明后创建
数据类型【】 数组名
数组名 = new 数据类型【长度】
二、声明时同时创建数组
数据类型[]数组名 = new 数据类型[数组长度]
数组在内存中的存储
数组名指向 数组的第一个元素
排序:
冒泡排序:
int nums []= {12,86,2,100,69,3};
//1、排序
for(int i =0; i < nums.length-1;i++) {
for(int j =0;j < nums.length-1-i;j++) {
if(nums[j] > nums[j+1]) {
int temp =nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
数组的扩容
//数组扩容(一)
int[]arr = {1,2,3,4,5};
int [] arr_new = new int[6];
for(int i =0; i < arr.length;i++) {
arr_new[i] = arr[i];
}
//为新数组赋值
arr_new[arr_new.length-1]=6;
for(int a : arr_new) {
System.out.print(a+" ");
}
System.out.println();
//数组扩容(二)
int[] copyof =Arrays.copyOf(arr, arr.length*2);//第一个参数是目标数组,第二个参数是扩容长度,并且返回一个新的数组;
for(int b : copyof) {
System.out.print(b+" ");
}
System.out.println();
//数组扩容(三)
/*
* src:表示赋值的源数组
* srcPos:代表从源数组哪一个元素开始复制(下标)
* dest:目标数组
* destPos: 从目标数组的哪一个元素开始粘贴源数组数据
* length:复制源数组的长度是多少
*/
int arr2[] = {10,20,30,40,50,60,70,80,90};
System.arraycopy(arr, 1, arr2, 3, arr.length-1);
for(int c: arr2) {
System.out.print(c+" ");//10 20 30 2 3 4 5 80 90
}
二维数组
方法
什么是方法
方法: 就是用来解决一类问题的代码的有序集合,是一个功能模块
比如
Scanner sc = new Scanner(Syatem.in)
sc.nextInt();===>接收用户从键盘输出的整形数据
sc.next();
方法的声明和调用
语法格式:
访问修饰符 返回类型 方法名(参数列表){
方法体
}
public(访问修饰符) static(关键字) void (返回类型)main(方法名)(String[] args)(参数列表string类型) {
System.out.println(k);(方法体)
}
访问权限修饰符
public 、private、protected、以及不写(默认)
private:只能用于当前类,一般情况下不能在别的类调用,
方法分类
根据方法是否带带参数、是否返回值、可分为4类
- 无参无返回值
- 无参带返回值
- 带参无返回值
- 带参带返回值
冒泡排序方法
可变参
- 当有可变参时,可变参必须放在最后
- 只能有一个可变参
- 当普通方法与参数列表同时被调用,只会调用普通方法,可变方法不会被调用
方法的重载
方法名相同,参数列表不同(与返回值没有关系)
面向对象
一个.java文件中可以有多个类,但是只能有一个public类,并且类名与文件名相同例如:
面向过程:
(人)面向对象:
对象:万物皆对象、客观存在的事物。类实例化对象。
对象:用来描述客观事物的一个实体一组属性和方法构成
人关注对象。人关注事物信息
类: 对象抽象出类
类是模型,确定对象将会拥有的特征(属性)和行为(方法)
特点:
类是对象的类型
具有相同属性和方法的一组对象的集合
对象是类的实例表现
方法:(能干什么)对象具有的各种动态行为
属性:(能不能) 对象具有的各种静态特征
面向对象都是基于面向过程;
类和对象的关系:
类是抽象的概念,仅仅是模板
对象是一个你能够看得到、摸得到的具体实体
类是对象的类型
对象是特定类型的数据
具体开发过程中,先定义类在实例化对象
单一职责原则:一个类只干一件事
单一职责原则,也称单一功能原则
英文为:Single Responsibility Principle(简称为SRP)
是面向对象设计的一个重要原则
一个类,应该有且只有一个引起变化的原因
在程序设计中,尽量把不同职责,放在不同职责中,即把不同的变化原因,封装到不同类中
功能越多,交融、耦合性越高,复用性越低
单一职责(面向对象)的应用
对象实例化
实例化对象的过程可以分为两个部分:
声明对象 Cat one
实例化对象 new Cat();
声明实例化对象 cat one = new cat();
声明对象在栈内存中开辟空间(内存固定)
实例化对象在堆内存空间开辟空间,并将地址值给栈内存(大小不固定,在编译时可以动态开辟所需要的内存空间)
对象信息存储在堆内存(声明是在栈内存中,因此只声明的话不能调用)
房子在堆内存中 房号在栈内存中
在堆内存中没有开辟空间就会报空指针异常
Cat one = new Cat();//要用类必须先实例化
Cat two = new Cat();
调两次;互相独立的个体,互不影响
多个对象可以指向同一块实例化空间:
Cat one = new cat();
cat two = one;同时拥有使用权
默认值问题
没有初始化变量值也可以运行
成员属性是具有默认值的
封装
构造方法:(对变量进行操作)不能被继承
在没有构造函数值之前,对象的成员变量是在对象创建之后通过setxxx修改器赋值,
构造函数是在创建对象的时候执行,在期间对成员变量进行初始化,问setxxx还需要不?
看需求,如果后期成员变量需要修改,则提供setXX修改器
- 构造方法与类名同名且没有返回值(但有return这个关键字)
- 构造方法的语句格式
public 构造方法名(){
//初始化代码
} - 只有在对象实例化的时候调用
- 当没有指定构造方法时,系统会自动添加无参构造方法
- 当有指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参构造方法
- 一个类中可以有多个构造方法(方法的重载)
构造方法分为带参和无参两种
注意*
构造函数不能有静态
成员函数不能调用构造函数
构造函数可以调用成员函数(直接方法名()来调用)
构造函数可以调用构造函数,但是不能出现回调(本类用this()、父类用super()都必须放在第一行,并且不能同时出现)
- 对于构造方法,下列叙述正确的是(ACD)
A. 构造方法的优先级一般比代码块低 //子类实例化时一般最后执行构造方法
B. 构造方法的返回类型只能是void型。 //构造方法没有返回值
C. 构造方法的主要作用是完成对类的对象的初始化工作 //概念
D. 一般在创建新对象时,系统会自动调用构造方法
class two01{
two01(){
System.out.println("base");
}
}
public class two extends two01 {
public static void main(String[] args) {
new two();
new two01();
}
//结果BaseBase实例化子类的时候子父类的构造也会被调用
}
this关键字(当前对象)
this的使用
- 调用成员变量,解决成员属性和局部变量名同名冲突
- 调用成员方法
- 调用构造方法this()
形式参数不给赋值也能用
当实例化对象的时候能调用多个构造方法
封装
- 将类的某些信息隐藏在类内部,不允许外部程序直接访问
- 通过该类提供的方法来实现对隐藏信息的操作和访问
隐藏对象信息
留出访问接口
特点 - 只能通过规定的方法访问数据
- 隐藏类的实例细节,方便修改和实现
封装的实现步骤:
包
作用:
-
管理Java文件
-
解决同名文件冲突
电脑是以文件的信息存储信息
src 源文件
定义包
语法:
package 包名
例: package org.oracle.animal
注意:- 必须放在java源文件的第一行
- 一个java源文件中只能有一个package语句
- 包名全部英文小写
- 命名方式: 域名倒叙 + 模块+功能
导入包
精确导包:org.oracle.entity.Cat cat1 = new org.oracle.entity.Cat();
常用系统包
Java.lang 包含java语言基础类
java.util 包含java语言中各种工具类
java.io 包含shuru、输出相关功能的类
static(可以被继承,因为具有唯一性因此不能被重写)
不能用this关键字
private不能被继承
static + 属性—静态属性
static + 方法—静态方法
static + 类—不存在
static + 方法内局部变量—不存在
静态成员随类的加载产生,直到销毁才回收
什么时候定义静态变量???
在同一类下,多个对象之间有相同的 属性和值,那么就可以将该属性和值从成员变量变为静态变量
什么时候定义静态函数???
当一个函数不访问成员变量时,即可定义为静态函数
静态函数中不能有成员变量
(因为成员变量在普通方法中必须实例化对象才能调用,而静态可以用类名调用)
好处:
节省空间
静态方法
- 静态方法可以直接调用同类中的静态成员
- 普通方法可以直接调用静态方法
- 静态方法不可以直接调用同类中的非静态成员
- 可以通过实例化对象后,对象调用的方式完成非静态成员调用
静态只能调静态
静态方法若想要调用普通方法,需要通过创建对象的形式利用对象调用普通方法
静态方法不能调this关键字
静态变量(静态方法区) 与成员变量(堆)的区别
生命周期:
成员变量随着对象的创建而创建,随着对象的消亡而消亡
静态变量随着类加载而存在,随着程序的结束而消亡
所属类不同
成员变量属于对象的,称之为类的特有属性
静态变量是属于类的,称之为类的属性,或者叫对象的共有属性
调用方式不同:
成员变量必须通过创建对象来调用,内部的话成员变量可以直接调用成员变量,但是静态函数不能直接调用成员变量,如果非要调用,只能创建对象,通过对象调用
静态变量可以在外界通过对象调用,也可以通过类来调用,内部的话静态可以调静态
代码块
通过{}可以形成代码块
方法类的代码块称为:普通代码块
类内的代码块称为:构造代码块
构造代码块前加+ static:静态代码块
代码块的执行顺序
- 无论实例化产生多少对象,静态代码块只执行一次
- 构造代码块随实例化过程调用
- 普通代码块随方法调用执行
继承
类与类之间的关系
使用已存在的类的定义作为基础建立新类
新类的定义可以增加新的数据或新的功能,也可以用父类功能,但不能选择性的继承父类
特点:利于代码的复用,缩短开发周期
继承的关系
满足A is a B 的关系就可以形成继承关系
如:猫、狗是动物
实现继承
使用extends实现继承
编写父类
class Animal{
//公共属性和方法
}
编写子类、继承父类
class Dog extends Animal{
//子类特用的属性和方法
}
子类可以调用父类的非私有
父类不能调用子类成员和子类属性
兄弟类之间的数据不能相互调用
重写
方法的重载:
- 重载在同一个类当中
- 方法名相同,参数列表不同(参数类型、参数个数、参数顺序)
- 与返回值类型无关
- 与访问权限修饰符无关
方法重写(方法重写属性不能重写) - 重写在父子类当中
- 方法名相同参数列表相同(参数类型、参数个数、参数顺序)
- 与返回值类型相同
- 与参数名称无关
- 与访问权限修饰符无关
重载
方法名相同
参数列表不同(个数、类型、顺序)
与访问权限修饰符无关
与返回值类型无关
重写
两同两小一大
方法名相同、参数列表相同(个数类型、顺序)
返回值、异常
访问权限修饰符
访问权限修饰符
super
子类访问父类成员
- 访问父类成员方法 super.printf()
- 访问父类属性 super.name
1、子类的构造的过程中必须调用其父类的构造方法
2、 如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类的无参构造方法
3、如果子类构造函数方法中既没有显式调用父类的构造方法,而父类又没有无参构造方法,则编译出错
4、使用super调用父类指定的构造方法,必须在子类的第一行
实例化顺序
子类实例化与父类有关?对
静态具有唯一性
子类无参构造方法
子类静态代码块
子类构造代码块
在实例化子类对象时,无论是调用有参还是无参子类构造方法,都会默认先调父类的无参构造方法
继承后的初始化顺序
1、父类静态成员
父类静态代码块
2、子类静态成员
子类静态代码块
3、父类对象构造(属性、构造代码块、构造方法)
4、子类对象构造(属性、构造代码块、构造方法)
子类对象实例化时,能否选择父类的构造形式(调用指定的构造方法)?可以:用super关键字
在静态里不能用super/super关键字
super 和this区别
this当前对象的引用
- 访问当前对象的成员方法
- 访问当前类的成员属性
- 访问当前类的构造方法
- 不能在静态方法中使用
super父类对象的引用 - 访问父类的成员方法
- 访问父类的成员属性
- 访问父类的构造方法
- 不能在静态中使用
在构造方法调用时super和this不能同时出现
object类
- object 类是所有类的父类
- 一个类中没有使用extends关键字明确标识继承关系,则默认继承object类(包括数组)
- java中每个类都可以使用Object中定义的方法
object类中的常用方法
tostring():返回当前对象本身的有关信息,按字符串对象返回
equals():比较两个对象是否是同一对象,是则返回true
hashCode():返回该对象的哈希代码值
getClass():获取当前对象所属的类信息,返回class对象
equals如果不重写与==一样比较的是引用地址
final
- 修饰类不允许被继承(更不能被重写)
- 修饰方法表示不允许被子类继承
final修饰的方法可以被继承
final不能修饰构造方法 - 修饰的变量不允许修改
方法内部的局部变量在使用前被赋值即可
类的成员变量》》只能在定义时、构造方法、构造代码块中进行
基本数据类型变量》》初始赋值之后不能更改
引用类型变量》》初始化之后不能在指向另一个对象,但指向的对象内容是可可变的 - 可配合static使用
- 使用final修饰可以提高性能,但会降低可扩展性
string是不能继承因为string被final修饰
被final修饰的类不能被继承,但是可以继承其他类
多态
设计模式(23种基础模式)
- 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结
- 设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案
- 项目中合理的运用设计模式可以完美的解决很多问题
- 每个模式在现实中都有相应的原理与之对应
- 每个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案
单例模式
- 一个朝代皇帝只有一个
- 军队的最高司令只有一个
- 一山不容二虎
计算机系统 - 驱动程序
- 打印机后台处理程序
- 线程池
- 缓存
- 日志
代码实现方案
1、饿汉式 在类加载时创建
2、懒汉式 第一次调用时实例化
目的:
使得类的一个对象称为该类系统中的唯一实例
定义:
一个类中有且仅有一个实例,并且自行实例化()向整个系统提供
要点: - 某个类只能有一个实例(static修饰)
- 必须自行创建实例(构造方法私有化)
- 必须自行向整个系统提供这个实例(getintance方法)
实现: - 只提供私有的构造方法
- 含有一个该类的静态私有对象
- 提供一个静态的共有方法用于创建、获取静态私有对象
优点:
1、在内存中只有一个对象,节省内存空间
2、避免频繁的创建销毁对象、提高性能
3、避免对共享资源的多重占用
缺点:
1、扩展比较困难
2、如果实例化的对象长期不利用,系统将默认为垃圾进行回收,造成对象状态丢失
适用场景:
1、创建对象时占用资源过多,但同时又需要用到该类对象
2、当系统内资源要求统一读写,如读写配置信息
3、当多个实例存在可能引起程序逻辑错误,如号码生成器
多态(Polymorphism)
概念:允许不同类的对象,对同一消息做出不同响应(动物都有吃东西的方法,不同的动物表现方式不同)
封装和继承几乎都是为多态准备的
分类:
- 编译时多态(设计时多态): 方法重载
- 运行时多态:java运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态
- 我们平时说的多态多指运行时多态
必要条件 - 满足继承关系
- 父类引用指向子类对象(向上转型)
向上转型和向下转型
通过instanceof运算符。来解决引用对象的类型,避免类型转化的安全性问题,提高代码的健壮性
抽象类
被abstract修饰的类是抽象类
- 抽象类无法实例化对象
- 抽象方法没有方法体
- 父类的抽象方法必须被子类重写
- 抽象方法必须在抽象类中
- 抽象类中不一定有抽象方法
- 抽象方法不能有private static final关键字
- 抽象方法在子类实现时访问权限修饰符必须大于父类
内部类
-
在Java中,可以将一个类定义到另一个类里面或者一个方法里面,这样的类称为内部类
-
与之对应,包含内部类的类被称为外部类
内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一包中的其他类访问该类,更好的实现了信息隐藏
提高了安全性
降低了可扩展性
分类
1、成员内部类
2、静态内部类
3、方法内部类
4、匿名内部类 -
匿名内部类
如果某个类的实例只是用一次,则可以将类的定义与类的创建,放到一起完成,或者在定义类的同时就创建一个类。以这种方法定义的没有名字的类称为匿名内部类
适用场景
只用到类的一个实例
类在定义后马上用到
给类命名并不会导致代码更容易 被理解
规则:
1、匿名内部类没有类型的名称、实例对象的名称
2、匿名内部类编译后存储名称是:外部类 $ 数字.class
3、匿名内部类没有构造方法(他没有名字)但是可以有构造代码块初始化变量
4、不能有private protected abstract static final 等修饰
5、匿名内部类中不能有静态成员
6、匿名内部类可以实现接口,也可以继承父类,但不可兼得
使用原则:
一般来说,匿名内部类用于继承其他类或实现接口,并不需要增加额外的方法,只是对继承方法的实现或者重写
匿名内部类返回的是一个对象的引用,所以可以直接使用或将其赋值给一个对象变量 -
成员内部类
1、内部类在外部使用时,无法直接实例化,需要借助由外部信息才能完成实例化操作
2、内部类的访问权限修饰符随意,但是访问范围会受到影响
3、内部类可以直接访问外部类的成员属性,如果有同名属性,默认会调用内部类属性
4、可以通过X(外部类).X(this).X(同名属性)的形式访问外部类的同名属性
5、内部类编译后的存储命名格式:外部类$内部类.class -
方法内部类
1、方法内部类不能写静态成员
2、方法内部类的使用:一般情况下返回方法内部类中的方法
接口
- 接口定义了某一批类所需要遵循的规范
接口不关心这些类的内部数据,也不关心这些 - 类里方法的实现细节,他只规定了这些类里必须提供某些方法
语法
[修饰符] interface 接口名 [extends 父接口一,父接口二]
接口与接口的关系继承类 - 接口中的方法默认有abstract修饰(因此他不能又方法体,但是Jdk1.8之后允许他有方法体,单必须被default static修饰,defalut可以被重写也可以被调用
static不能被重写但是可以调用:接口名.方法名调用 - 访问权限修饰符默认是public && 默认
- 当类去实现接口的时候,需要重写接口中的使用抽象方法,如果不想重写参考抽象方法
- 接口中包含的常量,默认被static final 修饰(因此不能被改变)
异常
什么是异常(影响程序的正常执行,可能 程序中断)
异常字面翻译就是‘意外’、‘例外’的意思、也就是非正常情况
异常本质上是程序上的错误
概念:在程序运行过程中、意外方式的情况,背离我们程序本身的意图的表现,都可以理解为异常
当程序在运行期间出现了异常,如果置之不理,程序可能会不正常运行、强制中断运行、造成用户数据丢失、资源无法正常释放,直接导致系统崩溃,显然这不是我们希望看到的程序中的异常
错误在我们编写程序的过程中会经常发生,包括编译期间(检查异常、中文逗号)和运行期间(runtimeexception、非检查异常)的错误
在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及的了
并且运行期间的错误往往是难以预料的
如何针对程序运行期间产生的异常进行合理的处理?
java提供了异常机制来进行处理,通过异常机制,我们可以更好地提升程序的健壮性
如何处理异常
try -catch-finally
throw
throws
自定义异常
异常链
异常的分类
在程序开发中,异常指不期而至的各种状况。他是一个事件,当发生在程序运行期间时,会干扰正常的指令流程
在java中,通过Throwable(所有异常的父类)及其子类捕捉各种不同的异常类型
Throwable有两个重要的子类:Exception 和Error
erro :是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行操作无关,而代表代码运行时JVM(JAVA虚拟机)出现的问题
例如,java虚拟机运行错误(VirtualMachineErro),当JVM不再有继续执行操作所需要的内存资源时,将出现OutOfMemoryError(内存溢出异常)我们编写程序时不需要关心这类异常
Ecxetion是程序本身可以处理的异常。异常处理通常只针对这种类型异常的处理。 Exception类的异常包括checked exception 和unchecked exception
在java应用程序中,异常处理机制为:抛出异常和捕获异常
抛出异常
- 当一个方法出现错误引发异常时、方法创建异常对象并交付运行时系统
- 异常对象中包含了异常类型和异常出现时的程序状态等异常信息
- 运行时系统负责寻找处理异常的代码并执行
- 在方法抛出异常后,运行时系统将转为寻找合适的异常处理器。
- 运行时系统从发生异常的方法开始,依次回查调用栈中的方法,当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器
- 当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着java程序的终止
public class One {
public static void main(String[] args) {
System.out.println(getNumber(0));
System.out.println(getNumber(1));
System.out.println(getNumber(2));
System.out.println(getNumber(4));
}
public static int getNumber(int num) {
try {
int result = 2/ num;
return result;
}catch (Exception exception) {
return 0;
}finally {
if(num == 0) {
return -1;
}
if(num==1) {
return 1;
}
}
}
}
//-1110
集合
为什么用集合,而不用数组
应用场景:
- 无法预测存储数据的数量
- 同时存储具有一对一关系的数据
- 需要进行数据的增删改查
- 数据重复问题
list
- 有序可重复的序列
- 可以精准的控制每个元素的插入位置,或删除某个元素的位置
- list的两个主要实现类Arraylist(底层是动态数组) 和linkedlist
- 底层由数组实现
- 动态增长
- 在列表尾部插入或删除非常有效
- 更适合查找或更新元素
- Arraylist 中的元素可以为null
list中需要注意的问题
1、添加元素
public static void main(String[] args) {
List list = new ArrayList();
//给集合添加数据
list.add("java");
list.add("go");
list.add("c");
list.add("python");
//循坏遍历集合中的内容
for (int i = 0; i < list.size(); i++) {
//list.get(i)返回的是obj类型的数据,而默认会调用tostring方法,而
//string重写了tostring方法如果加入自定义类型的数据就会返回引用地址值
System.out.println(list.get(i));
//System.out.println(((String)list.get(i)).toString());
}
}
==注意同tostring==
2、非空的判断
//如何判断非空
private static boolean isEmpty(List list) {
boolean flag = false;
/*
* 不能这样写有大bug
*/
// if(!list.isEmpty()&&list!=null) {
// flag = true;
// }
// return flag;
if(list!=null) {
if(list.size()!=0) {
flag = true;
}
}
return flag;
}
set
set:无序不可重复的集合,被称为集
hashSet
- hashset是set一个重要的实现类,称为hash集
- hashset中的元素无序不可重复
- hashset中只允许一个null元素
- 具有良好的存取查找性能
Iterator迭代器 - Iterator 接口可以以统一的方式对各种元素进行遍历
- hashNext()方法检测集合中是否还有下一个元素
- next()方法返回集合的下一个元素
1、添加元素
他会先将插入的对象与hashcode比较如果不成立则直接插入,如果相等则比较equals,equals如果不成立则插入
Set set = new HashSet();
Cat c1 = new Cat("昭昭", 12, "小花猫");
Cat c2 = new Cat("得福", 13, "小白猫");
Cat c3 = new Cat("富贵", 10, "富贵猫");
//将cat添加到set集合中
set.add(c1);
set.add(c2);
set.add(c3);
//遍历set中的元素
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
//为set添加cat对象
Cat c4 = new Cat("得福", 13, "小白猫");
System.out.println("****添加对象C4后****");
set.add(c4);
it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
//得福会直接插入
当重写equals方法后
得福便没再添加
map
- Map中的数据以键值对(k-v)的形式存储
- k-v 以entry类型的对象实例存在
- 可以通过key 快速的查找value
- 一个映射不能包含重复的键
- 每个键最多只能映射一个值
hashMap
基于哈希表的map接口实现
允许使用null值和null键
key值不允许重复
hashMap中的entry对象时无序排列的
public static void main(String[] args) {
Map <String,String> map = new HashMap<String,String>();
map.put("yello", "黄色");
map.put("black", "黑色");
map.put("green", "绿色");
//遍历map中的values数据
Iterator<String> it = map.values().iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
//遍历map中的key 和value
Set<Entry<String,String>>entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey()+ "," + entry.getValue());
}
}
集合排序
- 集合中基本数据类型排序
- 集合中字符串排序
- compartator接口
- comparable接口
使用collections类的sort()方法
sort(LIstanbullist)排序
对存放在list中的整型数据类型进行排序
对存放在list中的字符串进行排序
compartator接口 - 强行对某个对象进行整体排序的比较函数
- 可以将Comparator传递给sort方法(如collections.sort或者Arrays.sort)
int compare(T o1,To2)比较用来排序的两个参数
如果 1 <2 返回负数
如果1==2返回0
如果1> 2 返回正整数 - boolean equal(Object obj)指示某个其他对象是否“等于” 此Comparator
- 此方法可以被Object类中的equals方法覆盖,不必重写
comparable接口 - 此接口强行对实现它的每个类的对象进行整体排序
- 这种排序被称为类的自然排序,类的compareTo方法称他为自然比较方法
- 对于集合,通过collectiond.sort方法进行排序
- 对于数组,通过调用Arrays.sort方法进行排序
int compareTo(T 0)方法
该对象小于、等于、或者大于指定对象,则返回负整数、0、正整数