Java基础语法
内存图
方法
方法是什么
System.out.println()
类.对象.方法
方法是:1.语句的结合
2.包含于类或对象中
3.在程序中被创建,在其他地方被引用
原则:1个方法做1个功能
命名规则
- 项目名:随意
- 包名:小写,域名倒写,单词拼接_(下划线)
- 类:首字母大写和驼峰原则
GoodMan
- 类成员(成员变量):首字母小写+驼峰原则
lastName
- 局部变量:首字母小写+驼峰原则
- 方法名:首字母小写+驼峰原则
runRun()
- 常量:大写字母+下划线`MAX_VALUE
方法的定义
1.修饰符 返回值类型 方法名(参数类型 参数名){
方法体
return 返回值
}
2.包含一个方法头和一个方法体
3.
a.修饰符(告诉编译器如何调用此方法,定义了该方法的返回类型)
b.返回值类型 returnValueType
是方法返回值的数据类型,无返回值——>其关键字 void
c.方法名 方法的实际名字,方法签名:方法名+参数表
d.参数类型 参数:像占位符,被调用的时,传值给参数
参数列表:方法的参数类型+顺序+参数个数(方法可有可无参数)
形参:接受数据 public static int max(int num)
中num
是形参
实参:被调用时传给方法的数据 int max=max(10)
中10是实参
e.方法体 包含具体语句,定义方法的功能
4.方法就像C语言中的函数
方法的调用
- 调用方法 对象名.方法名(实际参数)
- Java中是值传递
- 静态方法(添加一个static)
- 非静态方法——>要有一个对象来调用
- 形参和实参
- 值传递和引用传递(传对象,实质传值)
- this关键字——调用当前类的方法
public class Student{
public static void say(){
System.out.println("学生");
}
}
public class Demo01{
public static void main(String[]args){
Student.say();
}
}
-
如果要实例化这个类,要new,
对象类型 对象名=对象值;
Student student=new Student(); student.say();
方法的重载
- 在一个类中,有相同的函数名称,但形参不同的函数
- 规则
- 方法名相同
- 参数列表不同,个数\类型\参数排列顺序······不同
- 返回值类型可一样可不一样,不可根据返回值类型判断是否是方法的重载
- 编译器会根据是否是方法的重载去调用该方法,否则不通过
public class Demo01{
public static void main(String[]args){
int max=max(10,10//实参);
System.out.println(max);
}
public static int max(int num1,int num2//形参){
int result=0;
if(num1==num2){
System.out.println("num1=num2");
return 0;//终止方法
}
if(num1>num2){
result=num1;
}else{result=num2;}
return result;
}
}
命令行传参
- 传递命令行参数给main()函数实现
- 在命令行中(通过
cmd
中输入值)——>在main()函数实现
public static Demo02{
public static void main(String[]args){
for(int i=0;i<args.length;i++){
System.out.println("args["+i+"]:"+"args[i]");
}
}
}
输入 this is a student
args[0]:this
args[1]:is
args[2]:a
args[3]:student
可变参数
- 传递同类型的可变参数给一个方法
- 方法声明中:在指定参数类型后加一个省略号(···)
- 一个方法中只能指定一个可变参数,必须是方法的最后一个参数
public static void main(String[] args) {
printMax(32,32,99,32,44,45,32);}
public static void printMax(double···numbers){
if(numbers.length==0){
System.out.println("No argument passed");
return;}
double result=numbers[0];
for(int i=1;i<numbers.length;i++){
if(numbers[i]>result){
result=numbers[i];
}
}
System.out.println("The max value is "+result);//The max value is 99.0
}
递归
- 少用,递归调用方法会在栈中分配一个空间(叫做栈帧(用于存储该方法的参数、局部变量等)),调用多次,增加空间,会溢出
- A方法调用A方法
- 递归结构包括两个部分:
- 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环
- 递归体:什么时候需要调用自身方法
public static int f(int n) {
if (n == 1)
return 1;
else {
return n * f(n - 1);
}
}
public static void main (String[]args){
System.out.println(f(5));//120
}
数组
数组的声明和创建
声明/定义
- 类型 []数组名;
int[] nums;
- 类型 数组名[];
int nums[];
创建
-
数组名=new 数组类型值;
nums=new int[10];
或者声明+创建
int[] nums=new int[10];
-
给元素赋值
nums[0]=1;
nums[1]=2;
-
数组不赋值默认为0
-
特点
- 长度确定,一旦创建,大小不可变
- 相同类型
- 数组对象在堆中,属于引用类型,数组本身就是对象,其元素就是对象的成员变量
数组初始化
静态初始化
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
数组的使用
- 打印
public class ArrayDemo01 {
public static void main(String[] args) {
int[]arrays={1,2,3,4,5};
//打印数组中的元素
for(int i=0;i<arrays.length;i++){
System.out.print(arrays[i]+" ");//1 2 3 4 5
}
}
}
- 增强打印(for-each循环)
public class ArrayDemo02 {
public static void main(String[] args) {
int []arrays={1,2,3,4,5};
//使用arrays.for直接生成
//使用增强for循环
// array是数组中的每个元素
//适合打印输出,但是取不到下标
for (int array: arrays) {
System.out.print(array);
}
}
}
- 使用数组进行排序
Arrays类
Arrays.toString(a)
(使用工具打印)可以打印出数组内的元素,直接打印出哈希值
public class ArrayDemo03 {
public static void main(String[] args) {
int[]a={1,2,3,4,3932,90};
System.out.println(a);//[I@7c30a502,打印出哈希值
System.out.println(Arrays.toString(a));//[1, 2, 3, 4, 3932, 90]
}
}
或者写一个方法打印
public class ArrayDemo03 {
public static void main(String[] args) {
int[]a={1,2,3,4,3932,90};
System.out.println(a);//I@7c30a502,打印出哈希值
//System.out.println(Arrays.toString(a));
printArray(a);
}
public static void printArray(int[]a) {
for(int i=0;i<a.length;i++){
if(i==0){
System.out.print("[");
}
if(i==a.length-1) {
System.out.print(a[i] + "]");
}else{
System.out.print(a[i]+",");
}
}
}
}
- Arrays类中的方法都是static修饰的静态方法,在使用时可以直接使用类名调用,而“不用”使用对象来调用(不是不能)
- 功能
- 给数组赋值:通过fill方法
Arrays.fill(a,0)
则数组中的元素都是0 - 对数组排序:通过sort方法,按升序
Arrays.sort(a)
- 比较数组:通过equals方法比较数组中元素值是否相等
- 查找数组元素:通过
binarySearch
方法能对排序好的数组进行二分法查找法操作
冒泡排序
- 两两选择(相邻)
- 下一轮少一次排序
import java.util.Arrays;
public class Demo04 {
public static int[] sort(int[]array) {
int temp=0;
for(int i=0;i<array.length;i++){
for(int j=0;j<array.length-i-1;j++){
if(array[j+1]<array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
return array;
}
public static void main(String[] args) {
int[]a={1,3,45,34,2,42};
int[] sort=sort(a);
System.out.println(Arrays.toString(sort));
}
}
- 优化减少循环次数 ,注释部分
import java.util.Arrays;
public class Demo04 {
public static int[] sort(int[]array) {
int temp=0;
for(int i=0;i<array.length;i++){
//boolean flag=false;
for(int j=0;j<array.length-i-1;j++){
if(array[j+1]<array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
//flag=true;
}
/*
if(flag=true)
break;
*/
}
}
return array;
}
public static void main(String[] args) {
int[]a={1,3,45,34,2,42};
int[] sort=sort(a);
System.out.println(Arrays.toString(sort));
}
}
稀疏数组
-
是一种数据结构
-
记录数组一共有几行几列,有多少不同值
-
把具有不同值的元素和行列及值记录在一个小规模的数组中,缩小程序的规模
public class ArrayDemo04 { public static void main(String[] args) { //创建一个二维数组 int[][] array1 = new int[11][11]; array1[1][2] = 1; array1[2][3] = 2; //输出原始数组 System.out.println("输出原始的数组"); for (int[] ints : array1) { for (int anInt : ints) { System.out.print(anInt + "\t"); } System.out.println(); } //转换为稀疏数组 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); //创建一个稀疏数组 //行数即为非零个数加1,列数为3 int[][]array2=new int[sum+1][3]; array2[0][0]=11; array2[0][1]=11; array2[0][2]=sum;//非零值个数 //遍历,找非零值 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]; } } } //输出稀疏数组 System.out.println("稀疏数组"); for(int m=0;m<array2.length;m++){ System.out.println(array2[m][0]+"\t"+array2[m][1]+"\t"+array2[m][2]+"\t"); } System.out.println(); //还原 //读取array2 int[][]array3=new int[array2[0][0]][array2[0][1]]; //给其他元素还原 for(int n=1;n<array2.length;n++){ array3[array2[n][0]][array2[n][1]]=array2[n][2]; } //打印 System.out.println("输出还原的数组"); for(int[]ints:array3){ for(int anInt:ints){ System.out.print(anInt+"\t"); } System.out.println(); } } }
对象
对象是什么
-
面对对象编程(
Object-Oriented Programming,OOP
)本质:以类的方式组织代码,以对象的组织(封装)数据
-
方法+属性——>类的成员;
- 属性(成员变量):对象(如Dog)所有的属性,具有性别\种类\尾巴·······(属性初始化不是必须的,有默认值)
- 方法:功能\动作,如睡\叫·······
-
对象:就是变量,引用类型的变量
-
对象:具体,静态的属性:属性
动态的行为:方法
类:抽象,对对象的抽象(把相同的、相似的“像”)
类是对象的模板,就是一个模板
-
特征:
- 封装
- 继承
- 多态
类和对象的创建和使用
- 类是一种抽象的数据类型,它是对某一类事物整体描述\定义,但是并不能代表某一个具体的事物,类是抽象的
- 对象是抽象概念的具体实例,对象是具体的(用动物,狗,蛇,动物是类,狗、蛇是对象)
- 类的UML图
对象是new出来的
使用new关键字创建对象
-
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中的构造器的调用
-
类中的构造器:构造方法,是在进行创建对象的时候必须调用的
-
特点:a. 必须和类的名字相同
b. 必须没有返回类型,也不能写void
public class Student{ String name;//null int age;//0 } //方法 public void study(){ System.out.println(this.name+"在学习"); } public static void main(String[]args){ //类:抽象的,要实例化 //类实例化后会返回一个自己的对象 //xh对象就是一个Student类的具体实例 Student xh=new Student();//xh是引用类型的变量,可以表示一个对应的对象 xh.name="小文";//对象的属性 xh.age=3; xh.study();//对象的方法 System.out.println(xh.name); System.out.println(xh.age); } }
4.对象:属性:字段Filed 成员变量 修饰符 属性类型 属性名 =属性值;
public char sex=M;
默认初始化:
数字:0 0.0
char:u0000
boolean:false
引用数组:null
构造器
-
作用:new实质在调用构造器(alt+insert 自动生成构造器)(注意有参/无参)
初始化对象的值
-
有默认构造器,调用无参构造,有有参构造时,无参构造得显示出来,没有有参构造时,不需要/可以显示无参构造
//一旦定义了有参构造,无参就必须显示定义
public class Person{ String name; public person(){ }//无参构造 public person(String name){ this.name=name; }//有参构造 } public class Application { public static void main(String[] args) { //new实例化了一个对象 Person person=new Person(); System.out.println(person.name);//null Person person=new Person("xh"); System.out.println("xh");//xh } }
封装
-
“高内聚,低耦合”:类内部数据操作细节自己完成,不允许外部干涉,仅仅暴露少量的方法给外部使用
-
封装(数据的隐藏)
信息隐藏:通常,应该禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来反问
-
属性私有(加private) get\set //方法不是私有的
作用:
- 提高程序的安全性,保护数据
- 隐藏代码的实际细节
- 统一接口
- 系统可维护增加了
public class Application {
public static void main(String[] args) {
Student s1=new Student();
s1.setName("xh");
System.out.println(s1.getName());//xh
}
}
public class Student {
//属性私有
private String name;//名字
private int id;//学号
private char sex;//性别
//提供一些可以操作这个属性的方法
//提供一些public的get,set方法
//快捷键alt+insert可以自动生成get\set方法
//get -获得这个数据
public String getName() {
return this.name;
}
//set 给这个数据设置值
public void setName(String name){
this.name=name;
}
}
继承
继承
-
继承:对某一批类的抽象,从而实现对现实世界更好的建模
-
extends:且类只有单继承(但是接口有多继承)
-
继承是类和类之间的关系
- 类和类 ——>extends 1->1
还有依赖、组合、聚合、继承等关系
2.类和接口——>implements 1->n
- 接口和接口——>extends 1->n
A extends B,C
//A接口有B,C两个接口的方法D implements A
//D能实现B,C两个接口的方法 -
继承是子类(派生类)和父类(基类)的关系,子类extends父类
public class Dog extends Animal{ }
-
继承的UML图
-
特点:
- 子类有父类的所有属性,子类继承了父类的所有成员变量和方法
- 一个父类可以由多个子类继承,一个子类只能继承一个父类,所有类默认继承object类
- 私有的东西无法被继承
- 在父类的修饰词中,优先选用public,protected
修饰词 | 本类 | 同一个包中的类 | 子类 | 其他类 |
---|---|---|---|---|
public | 可访问 | 可访问 | 可访问 | 可访问 |
protected | 可访问 | 可访问 | 可访问 | 不可访问 |
default(默认) | 可访问 | 可访问 | 不可访问 | 不可访问 |
private | 可访问 | 不可访问 | 不可访问 | 不可访问 |
super类
-
super用于访问父类中的成员变量
-
注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法(它们要求都要在方法的第一个,只能二选一)
-
super VS this
- 代表对象不同
- this:本身调用者这个形象
- super:代表父类对象的应用
- 前提
- this:没有继承也可以引用
- super:只能在继承条件才可以使用
- 构造方法
- this:本类的构造
- super:父类的构造
- 代表对象不同
-
当调用构造器的时候,注意无参/有参,有参构造器一定要用到super()
-
如果子类的构造方法中没有调用父类的构造方法,编译器会自动的加入对父类无参构造方法的调用 super()
(如果该父类没有无参的构造方法,会编译错误)
public class Person{
super();//编译器自动加入
}
public class Person {
protected String name="xh";
public void print(){
System.out.println("Person");
}
}
public class Teacher extends Person {
private String name="xh";
public void print(){
System.out.println("Teacher");
}
public void test1(){
print();//Teacher
this.print();//Teacher
super.print();//Person
}
}
public class Application {
public static void main(String[] args) {
Teacher t1=new Teacher();
t1.test1();
}
}
方法重写
- 与属性无关
- 需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但是不能缩小 public->protected->default->private
- 抛出的异常:范围可以缩小,但不能扩大
ClassNotFoundException->Exception(大)
-
子类和父类的方法必要一致,方法体不同
-
注意静态的方法和非静态的方法区别很大:
- 静态方法:方法的调用只和左边定义的数据类型有关(能执行哪些方法)
- 非静态(重写)(private不能重写)
-
为什么要重写:子类不一定需要或者不一定满足父类的功能
Alt+Insert 选override
B b=new A();//子类重写了父类的方法 b.test();//输出子类A中test()内容
-
重写使用super关键字
子类在重写父类的方法时,可以通过super关键字调用父类的版本。
7.重写和重载的区别
- · 重载是指在一个类中定义多个方法名相同但参数列表不同的方法,在编译时,根据参数的个数和类型来决定绑定哪个方法。
- · 重写是指在子类中定义和父类完全相同的方法,在程序运行时,根据对象的类型不同(而不是引用类型)而调用不同的版本。
多态
-
多态是方法的多态,属性没有多态
-
作用:使引用更灵活
-
存在条件:继承关系,方法需要重写,父类引用指向子类对象
Father f1=new Son();//f1.name是name Son()中的
public class Student extends Person{ public static void main(String[] args) { Student s1=new Student(); Person s2=new Student(); Object s3=new Student(); s2.eat();//子类重写父类的方法 s1.eat(); } public void eat(){ System.out.println("eat"); } } public class Person { public void eat(){ System.out.println("eat.eat"); } }
类型转换
instanceof
关键字
-
要求:有继承关系
类型之间的转换(同级转换,从属于继承关系,父与子)
高——>低(比如Object->Person->Student)
public class Application {
public static void main(String[] args) {
//Object>String
//Object>Person>Student
//Object>Person>Teacher
Object object=new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
Person obj=new Student();
//将这个对象转换为Student类型,就可以使用Student
((Student).obj).go();
}
}
自动类型转换
-
低——>高
Person person=student;
向上造型
- 父类 a =new 子类对象
- 父接口类型 =new 实现类对象
public class Demo05 { public static void main(String[] args) { //创建子类对象,会先创建父类对象(调用父类的构造器) //向上造型---自动类型转换--低到高 Animal a=new Dog();//a本质是引用 //a.ask();会报错//不是重写 // a是Animal类型,不能调用Dog类型的方法 //a能调用的只有Animal中的方法,但最终使用的是Dog重写的方法 //通过JVM可知a最后是Dog类型 a=new Pig();//打印pig//如果没有该语句,则if语句为真,打印wan if(a instanceof Dog) { //强制类型转换(前提是虚拟机认为a是Dog类型 Dog d1 = (Dog) a; d1.ask(); } } } public class Animal { char sex; int age; //实体类规范:添加无参构造器,为了方便被继承 public Animal(){ } public Animal(int age){ System.out.println("new Animal"); } public void sleep(){ System.out.println("sleep"); } public void eat(){ System.out.println("eat"); } } public class Dog extends Animal{ String name; //子类构造器中,第一行会默认添加 super() public Dog(){ //创建子类构造器之前,一定先创建父类构造器 super(10);//如果父类没有无参构造器,要么父类添加无参构造器,要么在子类中添加有参构造器 System.out.println("new Dog"); } public void ask(){ System.out.println("wan"); } public class Pig extends Animal { int weight; public Pig(){ super(); System.out.println("pig"); } }
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型(可能丢失一些自己本来的一些方法)
- 把父类转换为子类,向下转型,强制转换
- 方便方法的调用,减少重复的代码
static
-
static方法中不能对非static成员(对象成员)进行访问(静态)
-
static只执行一次
public class Person { { System.out.println("富强");//匿名代码块 } static{ System.out.println("民主");//静态代码块 } public Person(){ System.out.println("文明");//构造方法 } public static void main(String[] args) { Person person=new Person();//打印出 民主 富强 文明 //加载顺序先静态>匿名>构造 System.out.println(); Person person1=new Person();//静态代码块只执行一次 } } public class Student { private static int age;//静态的变量 多线程 private double score;//非静态的变量 public void run(){ System.out.println("run"); } public static void go(){ System.out.println("go"); } public static void main(String[] args) { Student s1=new Student(); s1.run(); go();//静态调用静态方法 }//打印 run go }
-
随机数+静态导入包
import static java.lang.Math.random; public class Random { public static void main(String[] args) { System.out.println(Math.random()); } }
抽象类
-
abstract修饰符可以用来修饰方法也可以用来修饰类,
如果修饰方法,那么该方法就是抽象方法;
如果修饰类,那么该类就是抽象类。
-
抽象类可以没有抽象方法,但是抽象方法的类一定要声明为抽象类
-
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的
-
抽象方法,只有方法的声明,没有方法的实现,它是让子类来实现的——>约束作用
-
不能同时使用final和abstract修饰类和方法——抽象类中的方法是要求被实现的,final是不能被更改的
-
抽象方法也不可以是static修饰的——被实现的方法能更改且重写—static只能使用一次
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
public abstract class Action{ //abstract 抽象类 }
-
作用:提高开发效率
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范!自己无法写方法 , 专业的约束!约束和实现分离:面向接口编程~
- 接口本质就是契约,就是约束
- 声明类的关键字是class,声明接口的关键字是interface
- 接口都要有实现类
-
接口的作用:
- 可以用抽象方法表示重要的行为标准——约束
- 可以把实现接口的类的对象的引用赋值给接口变量,该接口变量可以调用被该类实现的接口方法
——体现了该类根据接口里的行为标准给出的具体行为
-
接口的UML图
创建接口
直接创建//将class改为interface
实现接口
- 类可以实现接口 implements 接口
- 实现了接口的类,就需要重写接口中的方法(放在爆红的位置,alt+enter键自动补充方法)
- 实现接口的UML图
public interface UserService {
//接口中的所有定义都是抽象的
int ASD=99;//常量都是public static final
void add(String name);
void delete(String name);
void update(String name);
void query(String name);//方法都是public static
}
public class UerServiceImp implements UserService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
-
特点
-
约束
-
定义一些方法,让不同的人实现—多态
-
多态:不同类实现同一接口可能有不同的实现方法,接口变量在回调接口方法时可能有多种形态
-
定义的方法都是public static
-
定义的常量都public static final
-
接口不能被实例化,接口中没有构造方法
-
implements可以实现多个接口
-
接口也可以被继承——子接口与父接口关系
-
必须重写接口中的方法(非抽象类)
-
抽象类声明实现一个接口,但是可以不用重写接口中所有的方法
——抽象类可以重写接口中的方法,也可以直接拥有接口中的方法(即不用重写,被继承的类可以重写抽象类中的方法)
public class UerServiceImp implements UserService,TimeService{ //接口中的方法 ··· }
-
接口回调
- 声明接口变量
- 接口变量中存放对象的引用
- 接口回调
interface ShowMessage{
void s(String s);
}
class mm implements ShowMessage{
public void s(String s){
System.out.println(s);
};
}
public class Example{
public static void main(String args[]){
ShowMessage sm;//1.声明接口变量
sm=new mm();//2.接口变量中存放对象的引用
sm.s("你好呀!");//3.接口回调
}
}
接口和抽象类的比较
- abstract类和接口都可以有抽象方法
- 接口中只能有常量和抽象方法,不能有变量;抽象类中可以有常量、变量、抽象方法、非抽象方法
内部类
- 在一个类的内部再定义一个类
A类中定义了一个B类 //A类是外部类,B类是内部类
- 分类
- 成员内部类
- 静态内部类 //加static
- 局部内部类 //写在方法里
- 匿名内部类
- 一个Java类中可有多个class类,但是只能有一个public class
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new Apple().eat();//匿名内部类
UserService userService=new UserService() {
@Override
public void hello() {
}
};
public class Application {
public static void main(String[] args) {
Outer outer=new Outer();
//通过外部类来实例化内部类
Outer.Inner inner=outer.new Inner();
inner.getID();
}
}
}
}
class Apple{
public void eat(){
System.out.println("1");
}//成员内部类
}
interface UserService{
void hello();
}
public class Application {
public static void main(String[] args) {
Outer outer=new Outer();
//通过外部类来实例化内部类
Outer.Inner inner=outer.new Inner();
inner.getID();
}
}
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}//成员内部类,可以打印id
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
//静态内部类只要在内部类class前加一个static
//但是这样无法打印出id,因为加载顺序是先 static,只能执行一次,这样就无法加载前面的
}
}
异常
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户自定义异常类,只需继承Exception类即可。
- 在程序中使用自定义异常类,大体可分为以下几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理; 否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
- 在出现异常方法的调用者中捕获并处理异常
public class Exception {
public static void main(String[] args) {
int a=1;
int b=0;
try{//try监控区域
System.out.println(a/b);
}catch(ArithmeticException e){//catch捕捉异常
System.out.println("程序出现异常,变量b不能为0");
}finally{//处理善后工作
System.out.println("finally");
}
//finally 可以不要finally,假设IO流,资源,关闭
}
}
总结经验
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch (Exception) 来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch ,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用
printStackTrace()
去打印输出 - 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源