文章目录
Java
基于Java开发平台,系统,工具
- 构建工具:Ant,Maven,Jekins
- 应用服务器:Tomcat,Jetty,Jboss,WebSphere,weblogic
- Web开发:Spring,myBatis,Struts,Hibernate
- 开发工具:Eclipse,intellij idea,NetBean,Jbuilder
Java特性和有值
- 简单性:语法基于C语言,容易学。
- 面向对象:人的思维去写程序。
- 可移植性:Java的程序可以跨平台移植,核心是(JVM)。
- 高性能:
- 分布式:
- 动态性:
- 多态性:
- 安全性
- 健壮性
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
JDK是开发机环境,JDK包含了JRE、JRE是运行环境
JVM有两种方式(编译型)(解释型)
Java程序运行机制
- 编译型:javac.exe
- 解释型:java.exe
Java基础
注释(Comments)
- 平时写代码,项目结果一旦复杂起来,我们需要使用注释
- 注释并不会被执行的,写代码的人看
- 书写注释是一个非常好的习惯
Java中的注释有三种
- 单行注(Line comment)
- 多行注释(Block comment)
- 文档注释(JavaDoc)
标识符(identifier)
- 关键字(keyword):编程人员不可用将其作为变量的名称。
- Java的关键字有50个。
标识符注意点发
- 合法标识符举例:age,$salary,_value,__1_value
- 非法标识符:123abc,-salary,#abc
- 可以使用中文命名,但是不建议这样使用
数据类型
-
强类型语言:要求变量的使要用严格符合规定,所有变量都必须先定义后才能使用,更安全,速度较慢。
-
弱类型语言:要求变量的使要用符合规定,速度高。
-
Java的数据类型分为两大类
- 基本类型(primitive type)
- 引用类型(reference type)
什么是字节
- 位(bit):是计算机内部数据 储存的最小单位,11001100是一个八位二进制数。
- 字节(byte):是计算机中数据处理的基本单位,习惯上用大写B来表示
- 1B(byte,字节)=8bit(位)
- 字符:是指计算机中使用的字母,数字,字节符号
- 1bit表示1位
- 1Byte表示一个字节1B=8b
- 1024B=1KB
- 1024KB=1M
- 1024M=1G
- 1024G=1TB
电脑的32位和64位的区别是什么?
- CPU要求不同:CPU有32位和64位之分,32位的CPU只能安装32位系统,而64位的CPU既可以安装32位系统也可以安装64位系统。
- 运算速度不同:64位CPU的指令集可以运行64位数据指令,比32位CPU提高了一倍。
- 寻址能力不同:32位系统的处理器最大只支持到4G内存,而64位系统最大支持的内存高达亿位数,实际运用过程中大多数的电脑32位系统最多识别3.5GB内存,64位系统最多识别128GB内存。
- 软件兼容性不同:64位系统比32位系统的软件少,主要是64位系统推出的时间不长,所以64位系统的兼容性不如32位,虽然可以兼容32位软件,但是部分32位的软件在64位系统无法运行,但是目前的Win7 64位系统兼容性好了很多.
变量
-
变量是:就是可以变化的量。
-
java是一种强类型语言,每个变量都必须声明其类型。
-
java变量是程序中最基本的存储单元,其要元素包括变量名,变量类型和作用域。
- 变量作用于:类变量,实例变量、局部变量
public class Variable{ static int allNum=0; //类变量 String str="hello world!"; //实例变量 public void method(){ int i=0; //局部变量 } }
实例变量:从属于对象,如果不执行初始化,这个类型的默认值 0 0.0
布尔值:默认是false
除了基本类型,其余的默认值都是null
public static void main(String[] arges){
//局部变量,必须声明和初始化值
int i=10;
System.out.println(i);
}
float:有限、离散、舍入误差、大约、接近但不等于 最好完全使用浮点数进行比较
BigDecimal 工具类
常量(Constant)
-
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值
-
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
- 常量名一般使用大写字符
//final 常量名=值; final static double PI=3.14; //修饰符,不存在先后顺序 static final double PI=3.14;
变量的命名规范
- 所有变量,方法,类名:见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary除了第一个单词以外,后面的单词首字母大写(lastName)
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大和驼峰原则:Man,GoodMan
- 方法名:首字母和驼峰原则:run,runRun()
类型转换
- 由于Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。
低----------------------------------->高
byte,short,char->int->long->float->double
自动转换:低—高
int i=127;
double b=i;
强制转换:高—低 转换是要避免内存溢出问题
//int转换byte
int i=127;
byte b=(byte)i; //i不能大于127、如128《内存溢出》
- 运算中,不同类型的数据先转化为同一类型,然后进行运算。
- 不能对布尔值进行转换
- 不能把对象类型转换不相干的类型
- 在把高容量转换到低容量的时候,强制转换
- 转换的时候可能存在内存溢出,或者精度问题!
操作比较大数的时候,注意内存溢出问题
//JDK7开始新特性,数字之间可以用下划线分割
int money = 10_0000_0000;
int years = 20;
int total = money*years;//-474836480,计算的时候溢出
long total2 = money*years;//默认是int,转换之前已经存出问题!
long total3 = money*((long)years);//先转换为long、这样不会出问题
运算符(operator)
- Java语言支持如下运算符:
算数运算符:+,-,*,/,%,++,--
赋值运算符:=
关系运算符:>,<,>=,<=,==,!= instanceof
逻辑运算符:&&,||,!
位运算符:&,|,^,~,>>,<<,>>> #效率高
条件运算符:?
扩展赋值运算符:+=,-=,*=,/=
- 字符串连接符
int a=10;
int b=20;
System.out.prinln(a+b+""); //输出为:30
System.out.prinln(""+a+b); //输出为:1020
- 三元运算符
//X ? y : z
//如果x==true,则结果为y,否则结果为z
int score=70;
String type = score < 60 ? "不及格":"及格";
System.out.println(type)
包机制
- 为了更好地组织类、Java提供了包机制,用域区别类名的命名空间。
- 一般利用公司域名倒置作为报名。
- 为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用“import”语句可完成。
JavaDoc
- javadoc命令是用来生成自己API文档的
- 参数信息
- @author 作者名
- @version 版本
- @since 指明需要最早使用jdk版本
- @param参数名
- @return 返回值情况
- @throws 异常抛出情况
通过命令行 javadoc 参数 java文件
javadoc -encoding UTF-8 -charset UTF-8 hello.java
Scanner对象
-
java提供了一个工具,我们可以获取用户的输入。java.util.Scanner是Java5的新特征,通过Scanner类获取。
-
基本语法
Scanner s=new Scanner(System.in);
-
通过scanner类的nex()与nextLine()方法获取输入的字符串,在读取前我们一般需要 使用hasNex()与hasNextline判断是否还有输入的数据。
-
next():
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉。
- 只有输入有效字符后才有效字符后才将其后面输入的空白作为隔符或者结束符。
- next() 不能得到带有空格的字符串。
-
nextLine():
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
- 可以获取空白
循序结构
- Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
- 顺序结构是简单的算法结构。
- 语句与语句之间,框与框之间是按从上到下的顺序进行,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法。
选择结构(结构)
- if单选择结构
- 判断是否去执行,程序中用if语句来表示
- if双择结构
- 两个判断是需要双选择,if-else结构。
- 一旦其中一个else if 语句检测为true,其他的else if 以及else 语句都跳过执行。
- if多选择结构
- 很多时候的选择不仅仅只有两个,所以我们需要一个多选择结构来处理。
- 嵌套的if语句
- if语句可以用嵌套else if 语句中。
- switch多选择结构
- 多选择结构还有一行个实现方式就是switch case语句。
- switch case 语句中判断一个变量与一系列值中摸个值是否相等,每个值成为一个分支。
- switch语句中变量类型可以是:
- byte、short、int或者char。
- switch支持字符串String类型(java SE 7 开始)
- 同时case标签必须为字符串常量或字面量。
switch(){
case value :
//语句
break;//可选
case value :
//语句
break;//可选
//可以有任意数量的case语句
default: //可选
//语句
}
循环结构
-
while 循环
- 只要满足条件,循环一直执行下去。
-
do…while循环
-
如果不满足条件,则不能进入循环。但需要即是不满足条件,也至少执行一次。
-
While和do-While的区别:
-
while先判断后执行。do-while是实行后判断!
-
Do…while总是保证循环体会被至少执行一次!主要差别。
do{ //代码语句 }while(true);
-
-
for循环
- for循环是支持迭代的一种通用结构,是最有效,最灵活的顺换结构
-
在Java5中引入了一种主要用于数组的增强型for循环。
-
break continue
-
break用域强行退出循环,不执行循环循环中剩余的语句。
-
continue用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判断定。
方法
- java的方法是语句的集合,它们在一起执行一个功能。
- 方法包含于类或对象中
- 方法在程序中被创建,其他地方被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个语句块的集合。方法只完成一个功能。
方法定义
- java的方法类似于其它语言的函数,是一段 “用来完成特定功能的代码片段“。
- 方法包含一个方法头和一个方法体。下面是方法的所有部分:
- 修饰符:这是可选的,告诉编译器如何使用该方法。定义该方法的访问类型。
- 返回值:方法可能会返回值,returnValueType是方法返回值的数据类型。有些方法执行所需要的操作,但是没有返回值。这种情况下returnValuetype是关键字void。
- 形式参数:在方法被调用时用于接收外界输入的参数。
- 实参:调用方法的时实际传给方法的数据。
- 方法体:包含具体的语句,定义该方法的功能。
方法的重载
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
- 方法的重载规则:
- 方法名称必须相同
- 参数列表必须不同(个数不同,类型不同,参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
可变参数
-
JDK1.5开始,Java支持传递同类型的可变参数给一个方法。
-
在方法声明中,在指定参数类型后加个省略号(…)。
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
-
用法:
public class DemoMethod { public static void main(String[] args) { printExample("Hello",10,20,30); } public static void printExample(String str,int... numbers){ for (int i = 0; i < numbers.length; i++) { System.out.println(str+":"+numbers[i]); } } }
递归
-
A方法调用B方法,容易理解!
-
递归就是:A方法调用A方法!就是自己调用自己
-
利用递归可以简单的程序来解决一些复杂的问题。递归的能力在语用有限的语句来定义对象的无限集合。
-
递归结构包含两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归题:什么时候需要调用自身方法。
public class Demo02 {
public static void main(String[] args) {
System.out.println(f(5));//输出120
}
//递归方法
public static int f(int n){
if (n==1){
return 1;
}else {
return n*f(n-1);
}
}
}
数组(Array)
数组是最简单数据结构!
数组的定义
- 数组是相同类型数据的有序集合。
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 其中每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组声明创建
-
首先必须声明数组变量,才能在程序中使用数组。
dataType[] arrayRefVar; //首先的方法 或 dataType arrayRefVar[]; //效果相同,但不是首先方法
-
java语言使用new操作符来创建数组。
dataType[] arrayRefVar=new dataType[arraySize];
-
数组的元素是通过索引访问的,数组索引从0开始。
数组三种初始化
-
静态初始化
int[] a={1,2,3}; Man[] mans={new Man(1,1),new Man(2,2)};
-
动态初始化:包含默认初始化,默认为0
int[] a= new int[12]; a[0]=1; a[1]=2;
-
数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
数组的四个基本特点
- 其长度是确定的。数组一旦被创建、它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
-
下表的合法区间:[0,length-1],如果越界就会报错;
public static void main(String[] args) { int[] a=new int[2]; // [0],[1] System.out.println(a[2]); }
-
ArrayIndexOutOfBoundsException:数组下标越界异常!
-
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数据长度的确定的,不可变的。如果越界,报错。
数组使用
- 普通for循环
- For-Each循环
- 数组作方法入参
- 数组作返回值
多维数组
-
多维数组看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个维数组。
//以下二维数组a可以看成一个两行五列的数组 int a[][] = new int[2][5]; int[][] a={{1,2},{2,3}};
Arrays类
- 数组的工具类java.util.Arrays
- API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
- Arrays类中的方法都是static修饰的静态方法、在使用的时候可以直接使用类名进行调用,而不用使用对象来调用。
- 功能:
- 给数组赋值:通过fill方法。
- 对数组排序:通过sort方法,按升序。
- 比较数组:通过eqeuals方法比较数组中元素值是否相等。
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。
冒泡排序
-
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
private static int[] sort(int[] arrays) { //临时 int temp; //外层循环,判断我们这个要走多少次 for (int i = 0; i < arrays.length - 1; i++) { for (int j = 0; j < arrays.length - 1 - i; j++) { if (arrays[j + 1] > arrays[j]) { temp = arrays[j]; arrays[j] = arrays[j + 1]; arrays[j + 1] = temp; } } } return arrays; }
-
冒泡的代码,两次循环,外层冒泡轮数,里层依次比较。
稀疏数组
- 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数据中,从而缩小程序的规模
- 分拆问题:因为该二位数组的很多值是默认值0,因此记录了很多没有意义的数据。
- 解决:稀疏数组
面向对象(OOP)
面向过程 & 面向对象
-
面向过程思想
- 步骤清晰简单,第一步做什么,第二部最什么….
- 面对过程适合处理一些较为简单的问题
-
面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要那些分类,分类进行单独思考。才对某个分类下的细节进行面向过程思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
什么是面向对象
-
面向对象编程(Object-Oriented Programming, OOP)
-
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
-
抽象:编程思想
-
三大特性:
- 封装
- 继承
- 多态
-
从认识论角度考虑现有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
-
从代码运行角度考虑是现有类后有对象。类是对象的模板。
-
一个类里面只能用一次public,可以多个class
回顾方法及加深
- 方法的定义:
- 修饰符
- 返回类型
- break
- 方法名:注意规范、见名知意
- 参数列表:(参数类型,参数名)…
- 方法的调用:
-
静态方法:使用static的方法,其它类中可以直接使用(类名.方法名)
-
非静态方法: 要实例化使用 (new)
-
形参和实参:类型要对应
-
值传递和引用传递:对象,本质还是值传递
-
this关键字
-
类与对象的关系
- 类是一种抽象的数据类型,它是对某一些事务整体描述/定义,但是并不能代表某一个具体的事务。
- 动物,植物、手机、电脑….
- Person 类,Pet类,Car类等、这些类都是用来描述/定义某一类具体的事务应该具备的特点和行为
- 类是一个模板:抽象,类里面只有属性和方法,对象是一个具体的实例
- 类:静态的属性、动态的行为
- 对象是抽象概念的具体实例
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
创建于初始化
-
使用new关键字创建对象
-
使用new关键字创建的时候、除了分配内存空间之外,还还给创建好的对象 进行默认的初始化以及类中构造器的调用。
-
类中的构造器也成为构造方法,是在进行创建对象时候必有调用的。
构造器两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
封装
-
封装藏的藏
- 程序设计追求要追求"高内聚,低耦合"。
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
- 低耦合:仅暴露少量的方法给外部使用。
-
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应用通过操作接口来访问,这成为信息隐藏。
- 属性私有,get/set
- 提供程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可以维护增加
继承
-
继承的本质是对某一批类的抽象,从而实现对显示世界更好的建模。
-
extends的意思是“扩展”。子类是父类的的扩展。
-
java中类只有单继承,没有多继承!
-
私有(private )的无法被继承
-
继承是类和类之间的一种关系。除此之外类和类之间的关系还有依赖,组合,聚合等。
-
继承关系的两个类:
- 一个为子类(派生类)
- 一个为父类(基类)。
- 子类继承父类,使用extends来表示。子类和父类之间。从意义上讲应该具有“is a”的关系
-
object类:在java中所有的类,都默认直接或者间接继承Object类。
-
super:
- 调用父类的构造方法。
- 子类构造器,隐藏调用父类的无参构造,隐藏super()。
- super()调用父类的构造器,必须要在子类构造器的第一行。
- super和this不能同时调用构造方法!
-
super和this的区别:
- 代表的对象不同:
- this:本身调用这个对象
- super:代表父类对象的应用
- 前提:
- this:没有基础也可以使用
- super:只能在继承条件才可以使用
- 构造方法:
- this():本身的构造
- super():父类的构造!
- 代表的对象不同:
方法重写(Override)
重写:需要有继承关系,子类重写父类的方法!
子类的方法和父类的必要一致;方法体不同!
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩展大恒不能缩小。 public > protected > default > private
- 抛出的异常:范围,可以被缩小,但不能扩大。ClassNotFoundExcepxion —-> Excepxion(大)
- 为什么需要重写:
- 父类的功能,子类不一定需要,或者不一定满足!
以下测试
public class Test {
//静态方法和非静态方法区别
//静态方法://方法的调用只和在左边,定义的数据类型有关
//非静态:重写,否则不算重写
//子类继承了父类才能重写
public static void main(String[] args) {
A a=new A();
a.test();
//父类的引用指向了子类
B b=new A();//子类重写了父类的方法
b.test();
}
}
//继承
public class A extends B{
//重新
@Override //注解:有功能的注释 Alt + insert:override
public void test() {
super.test();
}
}
多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类是确定的,但可以指向对象对象的引用类型有很多 (父类,有关系的类)
- 多态是方法的多态,属性没有多态
- 父类和子类,有关系 类型转换异常! ClassCastException!父子泪之间处理问题。
- 没有继承关系就么有多态
- 多态存在条件:继承关系,子类重写父类方法,父类引用指向子类对象!Father f1=new Son();
- 不能被重写:
- static 方法,属于类,它不属于实例,静态方法不能被重写。
- final常量
- private方法
public class Application {
public static void main(String[] args) {
//一个对象实际类型是确定的,可以指向的引用类型就不确定了:父类的引用指向子类
//可以指向的引用类型就不确定了:父类的引用指向子类
//student 能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
//Person 可以、指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象执行那些方法、主要看对象左边的类型,和右边无关不大
s1.run();
s2.run();//子类重写了父类的方法,执行子类的方法
s1.eat();
//强制转换
((Student) s2).eat();
}
}
instanceof 类型转换 引用类型
子类转换为父类,可能丢失自己本来的一些方法!
//X和Y之间是否存在父子关系
System.out.println(X instanceof Y); //能不能编译通过!
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型;强制转换
- 方便方法的调用,减少重复的代码!
抽象: 封装,继承,多态! 抽象类,接口
static关键字详细
-
静态导入包
package com.example.oop; //静态导入包~ import static java.lang.Math.random; import static java.lang.Math.PI; public class Test { public static void main(String[] args) { //System.out.println(Math.random()); System.out.println(random()); System.out.println(PI); } }
-
测试static代码块
package com.example.oop; public class DemoStatic { //2.赋初始值~ { System.out.println("匿名代码块"); } //类一加载就直接执行,永久执行一次,跟类一块加载 //1.只执行一次~ static { System.out.println("静态代码块"); } //3 public DemoStatic() { System.out.println("构造方法"); } public static void main(String[] args) { DemoStatic demoStatic = new DemoStatic(); /** * 输出: * 1.静态代码块 * 2.匿名代码块 * 3.构造方法 */ System.out.println("=".repeat(20)); DemoStatic demoStatic1 = new DemoStatic(); /** * 1.匿名代码块 * 2.构造方法 */ } }
抽象类abstract
- 抽象方法,只有方法名字,没有方法的实现!
- 抽象类的所有方法,继承了它的子类,都必须要实现它的方法~
- 注意点:
- 不能new这个抽象类,只能靠子类去实现它:约束!
- 抽象类中可以写普通的方法~
- 抽象方法必须必须在抽象类中~
抽象的抽象:约束! 存在的意义抽象出来~ 提高开发效率
接口(interface)
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口:只有规范! 自己无法写方法~专业的约束! 约束和实现分离:面向接口编程~
-
接口就是规范,定义的是一组规则,体现了现实世界中“如果是你是…则必须能…”的思想。 如果你是天使,则必须能飞。
-
如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人。如果你是坏人,则必须欺负好人。
接口的本质是契约,就像我们人之间的法律一样。制定好后大家都遵守。
OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。 -
什么类的关键字是class,什么接口的关键字是interface
-
作用:
- 约束
- 定义一些方法,让不同的人实现~ 10 ------> 1
- public abstract
- public static final
- 接口不能被实例化~, 接口中没有构造方法~
- implements可以实现多个接口
- 必须要重写接口中的方法~
以下测试接口:
//抽象的思维~ Java
//interface 定义的关键字, 接口都需要有实现类
public interface UserService {
//常量~ public static final
int AGE=22;
//接口中所有定义的方法其实都是抽象的public abstract
void person(String type);
}
实现类(Impl)
//抽象类:extends~
//类 可以实现接口 implements 接口
//实现接口的类,就需要重写接口中的方法~
//多继承 ~ 利用接口实现多继承~
public class UserServiceImpl implements UserService,TimeService{
@Override
public void person(String type) {
}
//实现TimeService中的time()方法;
@Override
public void time() {
}
}
内部类
- 内部类就是在一个类的内部定义一个类、比如,A类中定义B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类。
- 一个java类中可以有多个class,但是只能有一个public class
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
以下测试:
public static void main(String[] args) {
Outer outer=new Outer();
//通过这个外部变量来实例化内部类~
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getId();
//没有名字初始化类
new Apple().eat();
}
异常机制(Exception)
什么是异常
-
写摸个模块,用户输入不一定符合要求。程序要打开某个文件,这个文件可能不存在或者文件格式不对。读取数据库的数据,数据可能是空的等。程序在跑着,内存或者硬盘可能满了。等等。
-
软件程序在运行过程中,非常可能上面提到这些异常问题,我们叫异常Exception,意思是例外。异常,怎么让我们写程序做出合理的处理。而不至于程序崩溃。
简单分类
要理解java异常处理是如何工作,需要掌握以下三种类型异常:
- 检查型异常:最具代表的检查性异常是用户用户错误或者引起的异常,这是程序员无法遇见的。例如打开一个文件不存在时,一个异常就发生了,这些异常在编译时不能被简单的忽略。
- 运行时异常:运行是异常可能是被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
异常体系结构
- Java把异常当作对象来处理,并定义一个基本java.lang.Throwable作为所有异常的超类。
- 在java API中已经定义了许多异常类,这些异常类分为两个大类,错误Error和异常Exception。
Error
- Error类对象java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- java虚拟机运行错误(Virtual MachineError),当jvm不再有继续执行操作所需的内存资源是,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError),连接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Exception
- 在Exception分支有一个重要的子类RuntimeExcep(运行是异常)
- ArrayIndexOutOfBoundsExcepion(数组下标越界)
- NullPointerException(空指针异常)
- ArithmetiException(算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这些异常的发生。
- error和exception的区别:
- Error:通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,java虚拟机(JVM)一般会选择终止线程;
- Exception:通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
-
抛出异常
-
捕获异常
-
异常处理五个关键字
- try:监控区域
- catch:捕获异常、catch(Throwable),catch(想要捕获的异常类型!)、捕获多个异常:从小到大!,e.printStackTrace();//打印错误栈站信息
- finally:可以不要finally,假设IO,资源,关闭!
- throw:主动抛出异常、throw new ArithmetiException(); 一般在方法中使用
- throws:假设方法中处理不了异常、方法上抛出异常
自定义异常
-
使用java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,还可以自定义异常。自定义异常类,只需继承Exception类即可。
-
在程序中使用自定义异常类,大体可分以下几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。
-
总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多种catch快后面,可以加个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源
以下测试:
//自定义的异常类
public class MyException extends Exception{
//传递数字>10
private int detail;
public MyException(int a) {
this.detail=a;
}
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
调用:
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:" + a);
if (a > 10) {
throw new MyException(a);//抛出
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
//增加一些处理异常的代码~
System.out.println("MyException=>" + 2);
}
}
}