Java基础语法
基本的dos命令
打开cmd的方式
- 开始+系统+命令提示行
- Win+R 输入cmd打开控制台
- 在任意的文件夹下面,按住shift+鼠标右键,在此处打开命令行窗口
- 资源管理器的地址栏前面加上cmd路径
基本Dos命令
1. #盘符切换
2. #查看当前目录下所有文件 dir
3. #切换目录 cd \d(跨盘符操作) f: cd.. 上返回级目录
4. #清理屏幕 cls (clear screen)
5. #退出终端 exit
6. #查看ip ipconfig
7. #打开应用
calc 打开计算机
mspaint 打开画图
notepad 打开记事本
8. #创建目录 md 目录名
9. #删除目录 rd 目录名
11.#文件创建 copy con 文件名
10.#文件删除 del 文件名
java
IDE
集成开发环境。
第一个java程序
- 编写代码:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
- 在一个java文件所在位置。可在其前面加cmd
进入cmd命令,可以在文件所在位置执行
javac HelloWorld.java 编译HelloWorld.java文件
java HelloWorld.java 运行HelloWorld.java文件
- java是大小写敏感的。
- 文件名 和 类名必须保持一致,并且首字母大写
java程序运行机制
- 程序运行机制:
<1>java基础语法
1.注释、标识符、关键字
java中的注释有三种:
- 单行注释 / /
- 多行注释 /* */
- 文档注释
标识符注意点 - 所有的标识符应该以字母(A-Z或a-z),美元符($),下划线(_)开始
- 首字母之后可以是字母(A-Z或a-z),美元符($),下划线(_)和数字的任意组合
- 标识符是大小写敏感的。
2.数据类型★
强类型语言
要求变量的使用符合规定,先定义后使用。
java数据类型分为两类,基本类型与引用类型
基本数据类型:
byte占一字节范围:-128-127
short占两个字节范围:-32768-32767
int占四个字节范围:-2147483648-2147483647
long占八个字节 定义时在后面加L
float占四个字节
double占八个字节
字符类型 char 占2个字节
Boolean类型:占一位只有true和false两个
引用类型:
类,接口,数组
//银行业务怎么表示?
//最好完全避免使用浮点数进行比较
//例如:
float f=0.1f;
double d = 1.0/1;
System.out.println(f==d); //false
float a1 = 2312312312312312313f;
float a2 = a1 + 1;
System.out.println(a1==a2); //true
3.类型转换
unicode编码,使得字符可以用数字表示。
char a='A'; (int)a=65.
4.变量、常量
//JDK7新特性,数字之间可以用下划线分割
int money = 10_0000_0000;
System.out.println(money);
//1000000000
public class Demo {
//类变量 static
static double salary = 2500;
//实例变量:从属于对象;如果不自行初始化,默认值0
//布尔值:默认值false
//除了基本类型,其他默认值为null
//类成员变量
String name;
int age;
//main方法
public static void main(String[] args){
//局部变量:必须声明和初始化值
int i = 10;
System.out.println(i);
//变量类型 变量名字 = new Demo();
Demo demo1 = new Demo();
System.out.println(demo1.age);
System.out.println(demo1.name);
}
//其他方法
public void add(){
}
}
常量
初始化之后不能再改变值!不会变动的值。
final 常量名=值;
final double PI=3.14;
常量名一般用大写字符。
变量命名规范
所有变量、方法、类名:见名知意
类成员变量:首字母小写和驼峰原则:monthSalary
局部变量:首字母小写和驼峰原则
常量:大写字母和下划线:MAX_VALUE
类名:首字母大写和驼峰原则:Man,GoodMan
方法名:首字母小写和驼峰原则:run(),runRun()
5.运算符
同c语言
有位运算符。&,|,^,~,>>,<< 左移*2,右移/2.效率高
幂运算 用到 Math类。 Math.pow(2,3) Math.abs(-2)
很多运算会用到工具类去做。
//字符串连接符 +
int a=10;
int b=20;
System.out.println(""+a+b);
//1020
System.out.println(a+b+"");
//30
//三元运算符
// x ? y : z
//如果x==true,结果位y,否则为z
6.包机制、JavaDoc
包机制
为了更好的组织类,java提供了包机制,用于区别类名的空间。
包的本质就是文件夹。
包语法的语法格式为:
package pkg1[. pkg2[. pkg3...]];
一般用公司域名倒置作为包名;
为了能够使用某一个包的成员,我们需要在java程序中明确导入该包。使用"import" 语句可完成此功能。
import package1[.package2...].(classname | *); *是通配符,会导入包下面所有的类。
JavaDoc
javadoc命令是用来生产自己API文档的
参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
cmd 有 javadoc - encoding UTF-8 -charset UTF-8 Doc.java命令
格式为:javadoc 参数 Java文件 生成javadoc
<2>java流程控制
1.用户交互Scanner
java.util.Scanner 是Java5新特征,可以通过Scanner 类来获取用户的输入
基本语法:
Scanner s = new Scanner(System.in)
通过Scanner类的next()与nextLine()方法获取输入的字符串。在读取之前一般需要用 hasNext() 与 hasNextLine()判断是否还有输入的数据。
//创造一个扫描器对象,用于接收键盘数据
Scanner s = new Scanner(System.in);
System.out.println("使用next方式接受:");
//判断用户有没有输入字符串
if(s.hasNext()){
String str = s.next();
System.out.println("输出的内容为:"+str);
}
//凡是属于IO流的类如果不关闭会一直占用资源,要养成好习惯用完就关掉
s.close();
next():
1.一定要读取到有效字符后才可以结束输入;
2.对输入的有效字符之前的空白,next()方法会自动将其去掉;
3.只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符;
4.next()方法不能得到带有空格的字符串。
nextLine():
1.以Enter为结束符,也就是说nextLine()方法是输出回车之前的所有字符;
2.可以获得空白。
2.顺序结构
java基本结构就是顺序结构,除非特别指明,都是按照顺序一句一句执行
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("使用nextLine()方式接受:");
String str = s.nextLine();
System.out.println("输出的内容为:"+str);
s.close();
}
3.选择结构
包括 if单选择结构,if双选择结构,if多选择结构,嵌套的 if 结构,switch多选择结构。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容:");
String s = scanner.nextLine();
//equals:判断字符串相等
if(s.equals("Hello")){
System.out.println(s);
}
scanner.close();
}
4.循环结构
public static void main(String[] args) {
//输入多个数字,求其总和与平均数
Scanner scanner = new Scanner(System.in);
double sum=0;
int num=0;
//循环判断输入,并在里面进行求和统计,当输入非数字时结束输入,输出结果
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
sum += x;
num++;
}
System.out.println("总和为:"+sum+"\n平均数为:"+sum/num);
scanner.close();
}
while, for, do..while循环同c语言。不过java for循环在刚开始初始化进入循环时也会判断条件。
//增强for循环 同c++
for(声明语句 : 表达式){
//代码句子
}
//声明语句:声明新的局部变量必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与数组元素的值相等。
//表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
//例如:
int [] numbers = {10,20,30,40,50};
for(int x:numbers){
System.out.print(x+" ");
}
//输出 10 20 30 40 50
5.break&continue
break,continue同c。
关于goto关键字
-
goto关键字很早就在程序设计语言中出现,尽管goto仍是Java的一个保留字,但是并未在语言中得到正式使用:Java没有goto,然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue。
-
“标签”是指后面跟一个冒号的标识符,如:label:
-
对Java来说唯一用到标签的地方是在循环语句之前,而在循环之前设置标签的唯一理由是:我们希望在其中嵌套的另一个循环,由于break和continue通常只中断当前循环,但若随同标签使用,他们就会中断到存在标签的地方。
//输出101-150之间的所有的质数 outer:for(int i=101;i<150;i++){ for(int j=2;j<i/2;j++){ if(i%j==0){ continue outer; } } System.out.println(i); }
6.练习
//打印5行三角形
for (int i = 1; i <= 5; i++) {
for(int j=5;j>i;j--)
System.out.print(" ");
for(int j=1;j<=i;j++)
System.out.print("*");
for(int j=1;j<i;j++)
System.out.print("*");
System.out.println();
<3>Java方法
1.方法的定义和调用
System.out.println(),那么他是什么呢?
System是一个系统的类,out是一个对象,println()是一个方法.
即:调用系统System类里out对象里的println方法。
Java方法是语句的集合,他们在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
设计方法的原则:
方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只能完成一个功能,这样利于我们后期的扩展。
方法的定义
java的方法类似与其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含一下语法:
/*
·修饰符:可选的,告诉编译器如何调用该方法,定义了该方法的访问类型
·返回值类型:方法可能会返回值。returnValueType 是返回值的数据类型。有些方法执行所需的操作,但没有返回值。这种情况下,returnValueType 是关键字void。
·方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
·参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或者变量。参数是可选的,方法也可以不包括任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
实参:调用方法时实际传递给方法的数据。
·方法体:方法体包含具体的语句,定义该方法的功能。
*/
修饰符 返回值类型 方法名(参数类型 类型名){
···
方法体
···
return 返回值。
}
方法调用
调用方法:对象名.方法名(实参列表)
java支持两种调用方法方式,根据是否返回值来选择。
int larger = max(30,40);
run();
return 0;//终止方法
搜索了解:值传递(Java) 和 引用传递。
2.方法的重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法重载的规则:
- 方法名称必须相同
- 参数列表必须不同(个数不同,或类型不同,参数排列顺序不同等)
- 方法的返回类型可以相同可以不同
- 仅仅返回类型不同不足以称为方法的重载
实现理论:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型逐个去匹配,以选择对应的方法。如果匹配失败,则报错。
3.命令行传递参数
有时候你希望运行一个程序的时候再传递给他消息。这要靠传递命令行参数给main()函数实现。
public class CommandLine {
public static void main(String[] args) {
for(int i=0; i<args.length;i++){
System.out.println("args["+i+"]"+args[i]);
}
}
}
cmd中执行:
文件路径下: javac Demo3_command.java 编译
直接 java Demo3-command 会报错:无法加载主类Demo3_command
需要路径移到src目录下 java com.lv.Method.Demo3_command
java com.lv.Method.Demo3_command this is black
//输出:
args[0]: this
args[1]: is
args[2]: black
4.可变参数
在方法声明中,在指定参数类型后加一个省略号(...)
一个方法只能电指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须得在它之前声明。
public static int printMax(double ... numbers)
了解即可。
5.递归
递归就是:A方法调用A方法!自己调用自己。
递归写的简洁,但是如果传入参数过大的话,性能慢。
<4>数组
1.数组声明创建
数组的定义:
数组是相同类型数据的有序集合。
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们。
数组声明创建:
首先必须声明数组变量,才能在程序中使用数组。
dataType[] arrays; //首选方法
dataType arrays[]; //效果相同,但不是首选方法
java方法用new操作符来创建数组,语法如下
dataType[] arrays = new dataType[arraysize]
数组的元素是通过索引访问的,从0开始
获取数组长度:arrays.length.
内存分析:
Java内存分析:
堆:存放new的对象和数组,可以被所有的线程共享,不会存放别的对象引用;
栈:存放基本变量类型(包含这个基本变量的具体数值),引用对象的变量(会存放这个引用在堆立面的具体地址)
方法区:可以被所有的线程共享,包含了所有的class和static变量
三种初始化:
//静态初始化
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;
2.数组特点
数组的四个基本特点:
- 其长度是确定的,一旦被创建,大小不可变
- 其元素必须是相同类型,不允许出现组合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
3.多维数组
//二维数组
int a[][] = new int[2][5];
//可以看出一个两行五列的数组
多维数组是数组的数组。具体同c。
4.Arrays类
数组的工具类 Java.util.Arrays
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是不用,不是不能)
具有以下常用功能:
给数组赋值:通过fill方法。
给数组排序:通过sort方法。
比较数组: 通过equals 方法比较数组中元素是否相等。
查找数组元素:通过binarySearch 方法能对排序好的数组进行二分查找法操作。
5.扩展:稀疏数组
当一个数组中大部分元素位0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组处理方式:
记录数组一共几行几列,有多少不同值
把具有不同元素的行列及值记录在一个小规模数组中,从而缩小程序规模。
压缩算法。
package com.lv.array;
public class Demo5_xishu {
public static void main(String[] args) {
//1.创建一个二维数组11*11 0:没有棋子 1:黑棋 2:白棋
int array1[][] = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 1;
//2.输出原始数组
System.out.println("输出原始的数组:");
for(int[] ints : array1){
for(int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
//转换为稀疏数组保存
//1.获取有效值的个数
int sum=0;
for (int i = 0; i < 11; i++)
for (int j = 0; j < 11; j++)
if (array1[i][j] !=0)
sum++;
System.out.println("有效值的个数"+sum);
//2.创建一个稀疏数组
int array2[][] = new int[sum+1][3];
array2[0][0]=11;
array2[0][1]=11;
array2[0][2]=sum;
//3。遍历二维数组,将非零的值,存放在稀疏数组中
int count=0;
for (int i = 0; i < array1.length; i++)
for (int j = 0; j < array1[i].length; j++)
if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
//4.输出稀疏数组
System.out.println("稀疏数组:");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0]+"\t"+array2[i][1]+"\t"+ array2[i][2]);
}
//还原稀疏数组
System.out.println("还原:");
//1.读取稀疏数组
int array3[][] = new int[array2[0][0]][array2[0][1]];
//2.给其中的元素还原它的值
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
//3.打印
System.out.println("还原的数组为:");
for(int ints[] : array3){
for(int anInt : ints)
System.out.print(anInt + "\t");
System.out.println();
}
}
}
<5>面向对象
1.什么是面向对象
面向对象编程(Object-Oriented Programming) OOP
本质:以类的方式组织代码,以对象的组织(封装)代码。
三大特性: 封装、继承、多态。
从代码运行角度看:是先有类后有对象,对象是类的模板
面向对象 & 面向过程
面向过程思想:
步骤清晰简单,第一步做什么,第二步做什么
面向过程适合处理一些简单的问题
面向对象思想:
物以类聚,分类的思维模式,思考问题首先解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思考。
面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
2.回顾方法及加深
方法的调用
静态方法:
//同一个包内的一个文件
//学生类
public class Student{
//静态方法
public static void say(){
System.out.println("学生说话");
}
}
//另一个文件
public class Demo1{
public static void main(){
//静态方法可以,类名.方法直接调用
Student.say();
}
}
动态方法:
//同一个包内的一个文件
//学生类
public class Student{
//非静态方法
public static void say(){
System.out.println("学生说话");
}
}
//另一个文件
public class Demo1{
public static void main(String[] args){
//实例化这个类 new
//对象类型 对象名 = 对象值;
Student student = new Student();
student.say();
}
}
同时如果是动态方法,需要实例化后才可以加载。
public class Demo1 {
public static void main(String[] args){...}
//和类一起加载
public static void a(){
b();//报红,因为类没有实例化,b方法不存在
}
//类实例化后才存在
public void b(){
}
}
形参实参
同c
值传递和引用传递
//引用传递,实质还是值传递
public class Demo1 {
public static void main(String[] args){
//实例化
Person person = new Person();
System.out.println(person.name); //null
change(person);
System.out.println(person.name);//小明
}
public static void change(Person person){
person.name = "小明";
}
}
//定义了一个Person类,有一个属性:name
//类似于c里的结构体
class Person{
String name; //null
}
this 关键字
3.类与对象的创建
(1)类与对象的关系
类是一种抽象的数据类型,它是对某一类事物的整体描述/定义,但是并不能代表某一个具体事物。
动物、植物、手机、电脑
Person类、Pet类、Car类等,这些类都是用来描述/定义一类具体的事物应该具备的特点与行为。
对象是抽象具体概念的具体实例
张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
能够体现处特点,展现出功能的是具体的实例,而不是一个抽象概念
(2)创建与初始化对象
使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间以外,还会给 创建好的对象 进行默认初始化以及对类中构造器的调用。
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有一下两个特点:
1. 必须和类的名字相同;
2. 必须没有返回类型,也不能写void。
//同一个包里的其中一个文件
public class Student {
//属性:字段
String name; //null
int age; //0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//另一个文件
public static void main(String[] args){
//类,抽象化,实例化
//类实例化后会返回以一个自己的对象!
//student对象就是一个Student类的具体实例!
Student xiaoming = new Student();
Student lucy = new Student();
xiaoming.name = "小明";
xiaoming.age = 18;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
//小明
//18
}
4.构造器详解
//同一个包里的其中一个文件
public class Person {
//一个类即使声明都不做,也会存在一个方法
//显示的定义构造器
String name;
//实例化初始值
//1. 使用new关键字,本质是在调用构造器
//2. 用来初始化值
public Person(){
}
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Person(String name){
this.name = name;
}
}
//另一个文件
public static void main(String[] args) {
//new 实例化了一个对象
Person person1 = new Person();
Person person2 = new Person("jack");
Person person3 = new Person("lucy",18);
System.out.println(person1.name+' '+person1.age); // null 0
System.out.println(person2.name+' '+person2.age); // jack
System.out.println(person3.name+' '+person3.age); // lucy 18
}
alt + insert 快捷键,构造构造器。
5.创建对象内存分析
![内存对象分析](C:\Users\lenovo\Documents\Tencent Files\2498626192\Image\QQ图片20220425194000.jpg)
6.封装详解
该露的露,该藏得藏
我们程序设计要追求"高内聚,低耦合"。高内聚就是类的内部操作细节自己来完成,不允许外部干涉;低耦合:仅暴露少量的方法供给外部使用。
封装(数据的隐藏)
通常,应禁止直接访问一个对象中的数据的实际表示,而应该通过操作接口来访问。这称为信息隐藏。
: 属性私有 get/set
//同一个包里其中一个文件
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("Jack");
System.out.println(s1.getName());
}
//另一个文件
//类 private:私有
public class Student {
//属性私有
private String name; // 姓名
private int id; // 学号
private char sex; // 性别
//提供一些可以操作这个属性的方法!
// 提供一些public的 get、set方法
//get方法 获得这个数据
public String getName() {
return this.name;
}
//set方法 给这个数据设置值
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
alt+insert 快捷键可以快速生成get/set方法。
封装作用:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护性增加
7. 继承详解
(1) 什么是继承
继承的本质是对某一批类的抽象,从而实现对现实世界的更好的建模。
extends的意思是”扩展“。子类是父类的拓展。
Java中只有单继承,没有多继承。
继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用关键字extends来表示。
在Java中,所有的类都直接或间接继承object类。
//同一个包里的父类文件Person
//在Java中,所有的类都默认或直接间接继承object类。
//Person 人 : 父类
public class Person {
//public
//protected
//default
//private
String name;
public void say(){
System.out.println(this.name+" say a word");
}
//子类文件Student
//学生 is 人: 派生类,子类
//子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person {
}
(2) super详解
私有的东西无法被继承
父类文件:
//在Java中,所有的类都默认或直接间接继承object类。
//Person 人 : 父类
public class Person {
//public
//protected
//default
//private
protected String name = "protectedjack";
public Person(){
System.out.println("Person被执行了");
}
public void print(){
System.out.println("Person");
}
}
子类文件:
//学生 is 人: 派生类,子类
//子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person {
public Student(){
//隐藏代码,调用了父类的无参构造
super(); //调用父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参执行了");
}
private String name = "jack";
public void print(){
System.out.println("Student");
}
public void test1(){
print(); //Student
this.print(); //Studnet
super.print(); //Person super调用父类方法
}
}
应用:
package com.lv.oop.demo05;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test1();
}
}
/*
Person被执行了
Student无参执行了
Student
Student
Person
*/
super注意点:
1. super调用父类的构造方法,必须在构造方法中的第一个
2. super 必须只能出现在子类的方法或者构造方法中
3. super 和 this 不能同时调用构造方法!
super 与 this 区别:
1. 代表对象不同:
this:本身调用这个对象
super:代表父类对象的应用
2. 前提
this:没有继承也可以使用
super:只能在继承条件下才可以使用
3. 构造方法
this():本类的构造
super():父类的构造
(3) 方法重写
子类重写父类的方法。(子类和父类有方法名称一样,但是功能不同,即需要重写)
子类:
public class A extends B{
public static void test(){
System.out.println("A=>test()");
}
}
父类:
//重写都是方法的重写,与属性无关
public class B {
public static void test(){
System.out.println("B=>test()");
}
}
应用:
public class Application {
public static void main(String[] args) {
//Student student = new Student();
//student.test1();
//方法的调用之和左边,定义的类型有关
A a = new A();
a.test(); //A=>test()
//父类的引用指向了子类
B b = new A();
b.test(); //B=>test()
}
}
如果我们把子类父类方法里的static去掉,会看见一个 O↑ 和O↓ 这个就是重写的标志
输出为:
A=>test()
A=>test()
因为静态方法是类的方法,非静态方法是对象的方法。有static时,b调用了B类的方法,因为b是用B类定义的。 没有static时,b调用的是对象的方法,而b是用A类new的,即b是A new出来的对象,因此调用了A的方法。
重写:需要有继承关系,子类重写父类的方法!
1. 方法名必须相同
2. 参数列表必须相同
3. 修饰符:范围可以扩大但不能缩小: public > Protected > Default > private
4. 抛出的异常:范围可以被缩小但不能扩大:ClassNotFoundException --> Exception(大)
<6>异常机制
1.什么是异常、
- 实际工作中,遇到的情况不可能是完美的。比如:你写的某个模块,用户输入不一定符合你的要求,你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等等……
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫做异常(Exception),意思是例外情况
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等
- 异常发生在程序运行期间,它影响了正常的程序执行流程
简单分类,分为以下三种的异常:
- 检查性异常:最具代表性的检查性异常就是用户错误或问题引起的异常,这是无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略
- 运行时异常:运行时异常是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时被忽略
- 错误ERROR:错误不是异常,而是脱离控制的问题。错误在代码中通常被忽略。例如 当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
2.异常体系结构
Java可以把异常当作对象来处理,并定义了一个 基类 java.lang.Throwable作为锁头的异常的超类
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误ERROR和异常Exception。
(1) Error错误
Error类对象由 Java虚拟机生成并输出,大多数错误与代码编写者所执行的操作无关
Java虚拟机运行错误 (Virtural MachineError),当JVM不再有继续执行操作所需要的内存资源时,将出现 OutOfMemoryError。当这些异常发生时,Java虚拟机(JVM) 一般会选择线程终止;
还有发生在虚拟机试图执行应用时,如 类定义错误 (NoClassDefFoundError) 、链接错误 (LinkageError)。这些错误是不可查的,因为他们在应用程序中的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
(2) Exception异常
在Exception分支中有一个重要的子类RuntimeException (运行时异常)
- ArrayIndexOutOfBoundsException (数组下标越界)
- NullPointerException (空指针异常)
- ArithmeticException (算术异常)
- Missing ResourceException (丢失资源)
- ClassNotFoundException (找不到类) 等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常发生;
Error 和 Exception的区别:
- Error 通常会是灾难性的致命性错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择中止线程;
- Exception 通常情况下是可以被程序处理的,并且在程序中应该尽可能去处理这些异常
3.Java异常处理机制
五个关键字:try、catch、finally、throw、throws
throw 抛出异常
public class Test2 {
public static void main(String[] args) {
try {
new Test2().test(1,0);
}catch (ArithmeticException e){
e.printStackTrace();
}
}
//假设方法中,处理不了这个异常,方法上抛出异常
public void test(int a,int b) throws ArithmeticException{
if (b==0){
throw new ArithmeticException(); //主动抛出异常,一般在方法中使用
}
}
4.处理异常
catch()
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
//假设要捕获多个异常,要从小到大! 快捷键:Ctrl + Alt + T
try { //监控区域
new Test().a();
System.out.println(a/b);
}catch (Error e) {
System.out.println("Error!");
}catch (Exception e) {
System.out.println("Exception!");
}catch (Throwable e){ //catch(想要捕获的异常类型!)
System.out.println("程序出现异常"); //如果出现对应的异常,会执行catch里操作
}finally { //处理善后工作 最后肯定执行
System.out.println("finally");
}
}
public void a(){b();}
public void b(){a();}
}
5.自定义异常
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常,只需继承Exception类即可。
在程序中使用自定义异常类,大体可以分以下几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
- 在出现异常方法的调用者中捕获并处理异常
//自定义异常类MyException
public class MyException extends Exception{
//如果传递数字>10;抛出异常
private int detail;
public MyException(int a){
this.detail = a;
}
@Override
public String toString() {
return "MyException{" + "detail=" + detail + '}';
}
}
//Test 测试
public class Test {
public void test(int a) throws MyException {
System.out.println("传递的参数为"+a);
if(a>10)
throw new MyException(a);
System.out.println("OK 不大于10");
}
public static void main(String[] args) {
try {
new Test().test(11);
} catch (MyException e) {
System.out.println("MyException =>" + e);
}
}
}
/* 输出结果:
传递的参数为11
MyException =>MyException{detail=11}
*/