Java的特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
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
Java开发环境搭建
- JDK下载与安装
- 配置环境变量
- JDK目录介绍
- HelloWorld及简单语法规则
- Notepad++安装和使用
注释
Java中的注释有3三种:
- 单行注释
//
- 多行注释
/* */
- 文档注释
/** * */
标识符
Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
关键字
标识符规则
- 所有的标识符都应该以字母(A-Z 或者a-z) ,美元符( $ )、或者下划线(_)开始
- 首字符之后可以是字母(A-Z 或者a-z) ,美元符($)、下划线(_)或数字的任何字符组合
- 不能使用关键字作为变量名或方法名。
- 标识符是大小写敏感的
- 合法标识符举例:
age、 $salary、_ value、_ 1_ value
- 非法标识符举例:
123abc、 -salary、 #abc
- 可以使用中文命名,但是一般不建议这样去使用,也不建议使用拼音,很Low
数据类型
Java的数据类型分为两大类
- 基本类型(primitive type)
- 引用类型(reference type)
基本单位
- 位(bit) :是计算机内部数据储存的最小单位,11001100是一个八位3进制数。
- 字节(byte) :是计算机中数据处理的基本单位,习惯上用大写B来表示,1B (byte,字节) = 8bit (位)
- 字符:是指计算机中使用的字母、数字、字和符号
换算
- 1 bit表示1位,
- 1Byte表示一个字节1B=8b。
- 1024B=1KB
- 1024KB=1 M
- 1024M=1G.
类型转换
- 由于Java是强类型语言, )所以要进行有些运算的时候的,需要用到类型转换。
低------------------------------------------------------>高
byte, short,char--> int --> long --> float --> double
- 运算中,不同类型的数据先转化为同一类型, 然后进行运算。
- 强制类型转换 由高到低
inti=128;
byte b = (byte)i; //内存溢出
- 自动类型转换 由低到高
注意点:
1.不能对布尔值进行转换
2.不能把对象类型转换为不相干的类型
3.在把高容量转换到低容量的时候,强制转换
4.转换的时候可能存在内存溢出,或者精度问题!
- 操作比较大的数的时候,注意溢出问题
- JDK7新特性,数字之间可以用下划线分割
int money = 10_ 0000_ 0000 ;
变量
- 是什么:就是可以变化的量!
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
type varName [=value] [{ ,varName[ =value]}];
//数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型变量。
注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
变量作用域
- 类变量:static
- 局部变量:必须声明和初始化
- 实例变量:从属于对象,如果不自行初始化,值为这个类型的默认值
数字0 、0.0
布尔false
除基本数据类型其余默认值都为null
常量
- 常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
- 所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名 = 值;
final double PI=3.14;
- 常量名一般使用大写字符。
变量命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则: monthSalary
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线: MAX VALUE
- 类名:首字母大写和驼峰原则: Man, GoodMan
- 方法名:首字母小写和驼峰原则: run(), runRun()
运算符
Java语言支持如下运算符:
- 算术运算符:
+, - , * , / , % , ++ ,--
- 赋值运算符:
=
- 关系运算符:
>, <, >=, <=,==, !=,instanceof
- 逻辑运算符:
&&, ||, !
- 位运算符:
&, |, ^, ~,>>,<<, >>>
- 条件运算符:
? :
- 扩展赋值运算符:
+=, -=, *=, /=
int b = a++; //执行完这行代码后, 先给b赋值,再自增
int b = ++a; //执行完这行代码前,先自增, 再给b赋值
<< 位运算左移 相当于 *2
>> 位运算右移 相当于 /2
//一般用于高效率的数值运算
优先级
包机制
- 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
- 包语句的语法格式为:
package pkg1[. pkg2[. pkg3...]];
- 一般利用公司域名倒置作为包名;
- 为了能够使用某一个包的成员, 我们需要在Java程序中明确导入该包。使用"import"语句可完成此功能
import package1[ . package2...]. (classname|*);
JavaDoc
- javadoc命令是用来生成自己API文档的
参数信息
- @author 作者名
- @version 版本号I
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
用户交互Scanner
- java.util.Scanner 是Java5的新特征,我们可以通过Scanner类来获取用户的输入。
- 基本语法
Scanner S = new Scanner(System.in);
- 通过Scanner类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要使用 hasNext() 与 hasNextLine() 判断是否还有输入的数据。
next():
1、 一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
4、 next() 不能得到带有空格的字符串。
nextLine():
1、以Enter为结束符,也就是说 nextLine() 方法返回的是输入回车之前的所有字符。
2、可以获得空白。
顺序结构
- JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
- 顺序结构是最简单的算法结构。
- 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
选择结构
- if单选择结构
- if双选择结构
- if多选择结构
- 嵌套的if结构
- switch多选择结构
if单选择结构
- 我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
if(布尔表达式){
//如果布尔表达式为true将执行的语句
}
if双选择结构
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if多选择结构
if(布尔表达式1){
//如果布尔表达式1的值为true执行代码
}else if( 布尔表达式2){
//如果布尔表达式2的值为true执行代码
}else if( 布尔表达式3){
//如果布尔表达式3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
嵌套的if结构
if(布尔表达式1){
////如果布尔表达式1的值为true执行代码
if(布尔表达式2){
////如果布尔表达式2的值为true执行代码
switch多选择结构
- switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
switch语句中的变量类型可以是:- byte、short, int 或者char.
- 从JavaSE7开始switch支持字符串String类型了
- 同时case标签必须为字符串常量或字面量。
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
循环结构
- while循环
- do...while循环
- for循环
在Java5中引入了一种主要用于数组的增强型for循环。
while循环
while是最基本的循环,它的结构为:
while(布尔表达式) {
//循环内容
}
- 只要布尔表达式为true,循环就会一直执行下去。
- 我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
- 少部分情况需要循环一直执行,比如服务器的请求响应监听等。
- 循环条件一直为true就会造成无限循环 [死循环], 我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死奔溃!
do...while循环
- 对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do...while循环和while循环相似,不同的是, do...while循环至少会执行一次。
do {
//代码语句
}while(布尔表达式);
While和do-While的区别:
- while先判断后执行。
- dowhile是先执行后判断!
- do...while总是保证循环体会被至少执行一次!这是他们的主要差别。
for循环
- for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
- for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化;布尔表达式;更新) {
//代码语句
}
注意
- 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
- 然后,检测布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
- 执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。
- 再次检测布尔表达式。循环执行上面的过程。
print和println输出的区别
//println输出完会换行
//print输出完不会换行
增强for循环
for(声明语句:表达式)
//代码句子
- 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
- 表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
break continue
- break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
- continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
关于goto关键字 - goto关键字很早就在程序设计语言中出现。 尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;
- Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子————带标签的break和continue.
- "标签” 是指后面跟一个冒号的标识符,例如: label:
- 对Java来说唯一用到标签的地方是在循环语句之前。 而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
方法
- Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合。
- 方法包含于类或对象中。
- 方法在程序中被创建,在其他地方被引用。
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一一个方法只完成1个功能,这样利于我们后期的扩展。
方法定义
- Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义个方法包含以下语法:
- 方法包含一个方法头和一个方法体。
下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型:方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是-个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
修饰符 返回值类型 方法名(参数类型 参数名){
方法体
return返回值;
}
- 方法体:(方法体包含具体的语句,定义该方法的功能。
方法调用
- 调用方法:对象名.方法名(实参列表)
- Java支持两种调用方法的方式,根据方法是否返回值来选择。
- 当方法返回-一个值的时候,方法调用通常被当做一个值。
- 如果方法返回值是void,方法调用一定是一条语句。
方法的重载
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法的重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、等参数类型去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
命令行传参
- 有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
可变参数
- JDK 1.5开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(..)。
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
递归
- 递归:A方法调用A方法! 就是自己调用自己。
- 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。.
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
数组
- 数组是相同类型数据的有序集合.
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 其中,每一个数据称作一个数组元素每个数组元素可以通过一个下标来访问它们.
数组声明创建
- 首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar;
//首选的方法
或
dataType arrayRefVar[];
//效果相同,但不是首选方法
- Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
- 数组的元素是通过索引访问的,数组索引从0开始。
- 获取数组长度:
arrays . length
数组的四个基本特点
- 其长度是确定的。数组- -旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
Java内存分析
数组三种初始化
静态初始化
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
动态初始化
int[] a = new int[2];
a[0]=1;
a[1]=2;
数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
数组边界
- 下标的合法区间: [0, length-1],如果越界就会报错;
- ArrayIndexOutOfBoundsException :数组下标越界异常!
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可变的。如果越界,则报: ArrayIndexOutofBounds
数组使用
- for循环
- For- Each循环
- 数组作方法入参
- 数组作返回值
多维数组
- 多维数组可以看成是数组的数组,比如=维数组就是一个特殊的一 维数组,其每一个元素都一个一维数组。
二维数组int a[][] = new int[2][5];
Arrays类
- 数组的工具类java.util.Arrays
- 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
- 查看JDK帮助文档
- Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是"不用"而不是"不能")
具有以下常用功能:
- 给数组赋值:通过fill方法。
- 对数组排序:通过sort方法,按升序。
- 比较数组:通过equals方法比较数组中元素值是否相等。
- 查找数组元素: 通过binarySearch方法能对排序好的数组进行二分查找法操作。
- 输出数组的方法:Arrays.toString(数组名)
冒泡排序
- 冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
- 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
- 我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为0(n2)。
稀疏数组
- 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
-
把具有不同值的元素和行列及值记录在-一个小规模的数组中,从而缩小程序的规模,如下图:左边是原始数组,右边是稀疏数组
面向对象编程
面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观.上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
- 面向对象编程(Object-Oriented Programming, OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
- 抽象
- 面向对象三大特性:
- 封装
- 继承
- 多态
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
方法
- 静态方法:static
//可直接调用
student.say( );
- 非静态方法
//实例化这个类 new
//对象类型 对象名 = 对象值;
Student student = new Student( ) ;
student.say( );
值传递和引用传递
- 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
- 引用传递是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
- Java都是值传递
类和对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体描述定义,但是并不能代表某一个具体的事物.
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念.
创建与初始化对象
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
构造器
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。
并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- 一个类即使什么都不写,它也会存在一个方法
构造器作用
1.使用new关键字本质是在调用构造器。
2.初始化对象的值
- 有参构造:一旦定义了有参构造,无参就必须显示定义
public class Application {
public static void main(String[] args) {
// 使用new关键字实例化的对象
Person person = new Person("lisi");
System.out.println(person.name);
}
}
public class Person {
String name;
int age;
// 无参构造
public Person(){
// this.name="张三";
}
// 有参构造
public Person(String name){
this.name=name;
}
//alt+insert 自动生成构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
创建对象分析图
封装
- 我们程序设计要追求"高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问-个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- 属性私有,
get/set
私有属性:private
提供一些可以操作这个属性的方法!
- 提供一些public的get.set方法
//get获得这个数据
public String getName(){
return this.name;
}
//set给这个数据设置值
public void setName(String name){
this.name = name ;
}
alt+insert
自动生成get/set 方法
封装优点
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护增加了
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extends的意思是“扩展”。子类是父类的扩展。
- JAVA中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义.上讲应该具有"is a"的关系.
public class Student extends Person{
}
- object类:在Java中, 所有的类,都默认直接或者间接继承0bject
- super
super(); //调用父类的构造器,必须要在子类构造器的第一行
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中!
3.super和this不能同时调用构造方法!
super 和 this的对比:
代表的对象不同:
- this:本身调用者这个对象
- super:代表父类对象的应用
前提
- this:没有继承也可以使用
- super:只能在继承条件下才可以使用
构造方法
- this() ;本类的构造
- super():父类的构造!
方法重写
- 重写都是方法的重写,和属性无关
public class Application {
public static void main(String[] args) {
// 方法的调用只和左边定义的数据类型有关
Student student =new Student();
student.test();
// 父类的引用指向了之类
Person person =new Student();
person.test();
}
}
public class Student extends Person{
public static void test(){
System.out.println("Student=>test()");
}
}
public class Person {
public static void test(){
System.out.println("Person=>test()");
}
}
静态的方法和非静态的方法区别很大!
- 静态方法: 方法的调用只和左边定义的数据类型有关
- 非静态:重写
- 重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表列表必须相同
3.修饰符:范围可以扩大但不能缩小: public>Protected>Default >private
4.抛出的异常:范围,可以被缩小,但不能扩大;ClassNotFoundException --> Exception(大) - 重写,子类的方法和父类必要一致;方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足!
2.Alt + Insert ; override(重写);
- ctrl+h :查看类的层次结构
多态
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
- 注意:多态是方法的多态,属性没有多态性。
- instanceof
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();
object s3 = new Student( );
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
s2.eat(); //子类重写了父类的方法,执行子类的方法
s1.eat( );
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系类型转换异常! ClassCastException!
3.存在条件: 继承关系,方法需要重写,父类引用指向子类对象!
Father f1I= new Son();
不可重写和多态
- static 方法, 属于类,它不属于实例
- final 常量;
- private方法; |
instanceof (类型转换) 引用类型
作用
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型:
3.把父类转换为于类,向下转型: 强制转换
4.方便方法的调用,减少重复的代码!
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
- 注意
1.不能new这个抽象类,只能靠子类去实现它;约束!
2.抽象类中可以写普通的方法~
3.抽象方法必须在抽象类中~
抽象的抽象:约束~
接口
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你...则必须能..”的思想。
- 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
- OO的精髓,是对对象的抽象,最能体现这一点的就是接口。
声明类的关键字是class.声明接口的关键字是interface
- 接口中的所有定义的方法其实都是抽象的 public abstract
- interface定义的关键字,接口都需要有实现类
作用:
1.约束
2.定义一些方法,让不同的人实现~ 10--- >1
- public abstract
- public static final
5.接口不能被实例化,接口中没有构造方法 - implements 可以实现多个接口
7.必须要重写接口中的方法~
内部类
- 内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
1.成员内部类
public class Outer {
private int id;
public void out(){
System.out.print1n("这是外部类的方法");
}
class Inner{
public void in(){
System.out.print1n("这是内部类的方法");
}
}
}
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类米实例化内部类~
Outer. Inner inner = outer.new Inner( ) ;
}
2.静态内部类
public class Outer {
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
}
}
3.局部内部类
public class Outer {
//局部内部类
public void method(){
class Innerf{
public void in () {}
}
}
}
4.匿名内部类
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用讲实例保存到变量中~
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
异常机制
- 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
分类
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
异常体系结构
- Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
-
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
Error
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM) 一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError) 、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Exception
- 在Exception分支中有一个重要的子类RuntimeException (运行时异常)
- ArraylndexOutOfBoundsException (数组下标越界)
- NullPointerException (空指针异常)
- ArithmeticException (算术异常)
- MissingResourceException (丢失资源)
- ClassNotFoundException (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
- Error和Exception的区别: Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虛拟机(JVM) 一般会选择终止线程; Exception通常情况 下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
- 抛出异常
- 捕获异常
异常处理五个关键字
try、catch、finally、throw、throws
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
- 在程序中使用自定义异常类,大体可分为以下几个步骤:
1.创建自定义异常类。
2.在方法中通过throw关键字抛出异常对象。
3.如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
4.在出现异常方法的调用者中捕获并处理异常。
总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch (Exception) 来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源