内部类的作用:
内部类除了必须定义在其他类里面之外,还有如下区别:
成员内部类(方法外,外部类里面定义的)的 class 文件的格式是 OuterClass$InnerClass.class。
当调用非静态内部类的实例方法时,必须有一个非静态内部类实例,而非静态内部类实例必须寄生在外部类实例里。
1 OuterClass outer = new OuterClass();
2 (OuterClass.)InnerClass inner = outer.new Inner();
3 或
4 (OuterClass.)InnerClass inner = new OuterClass().new Inner();
使用 static 来修饰一个内部类,则这个内部类就属于外部类本身。静态内部类可以包含静态成员,也可以包含非静态成员,但是静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
静态内部类是外部类的一个静态成员,因此外部类的所有方法、所有初始化块中可以使用静态内部类来定义变量、创建对象。
外部类依然不能直接访问静态内部类的成员,但可以通过类名(或对象)作为调用者访问静态内部类的成员。
PS Java 还允许在接口里定义内部类,接口里的内部类默认是 public static 修饰
1.2.1 创建静态内部类实例
1 (OuterClass.)InerClass iner = new (OuterClass.)InnerClass();
声明周期和所在方法相同,生成 class 文件 格式为:OuterClass$NInnerClass.class。对比成员内部类,多了一个数字(N),因为同一个类了里可能有两个以上同名的局部内部类。
局部内部类若访问了局部变量(方法中定义的),则会自动给改变量加上 final 修饰符,意味着不能修改局部变量的值。
适合创建只需要使用一次的类,定义格式如下:
1 new 实现接口()|父类构造器(实参列表){
2 //类体
3 }
匿名内部类必须继承一个父类,或实现一个接口,且最多继承一个父类或实现一个接口。
规则:
当通过实现接口创建匿名内部类时,括号里不能有参数;
当通过继承父类来创建匿名内部类时,将拥有和父类相似的父类构造器(相同的形参列表),会根据参数列表调用父类构造器。类体里可以重写父类的普通方法。
同样的匿名内部类访问局部变量时,会自动添加 final 修饰。
异常是指在程序的运行过程中所发生的不正常的情况,它会中断正在运行的程序。java中通过异常处理机制为程序提供异常处理的能力,保持程序继续运行而不中断!
涉及异常处理的常用关键字有:try、catch、finally、throws、throw
把有可能产生异常的代码放到try代码块中,catch代码块负责捕获并处理异常。
Exception是所有异常类的直接或者间接父类。往下又分为 RuntimeException 和 检查时异常。检查时异常要求编译时必须对其进行异常处理,而 RuntimeException 没有要求。
运行时异常:包括RuntimeException及其所有子类。不要求程序必须对它们作出处理,比如InputMismatchException、ArithmeticException、NullPointerException等。即使没有使用try-catch或throws进行处理,仍旧可以进行编译和运行。如果运行时发生异常,会输出异常的堆栈信息并中止程序执行。
Checked异常(非运行时异常):除了运行时异常外的其他异常类都是Checked异常。程序必须捕获或者声明抛出这种异常,否则出现编译错误,无法通过编译。处理方式包括两种:通过try-catch捕获异常,通过throws声明抛出异常从而交给上一级调用方法处理
常见的运行时异常
ArithmeticException:数学计算异常。比如除数为0 InputMismatchException:输入不匹配异常 ArrayIndexOutofBoundsException:数组下标越界异常。 NullPointException:空指针异常,对象没有初始化就使用时,jvm会抛出该异常 IllegalArgumentException:非法参数异常。 ClassCastException:强制类型转换异常。 NumberFormatException:数字格式化异常。比如把“abc”格式化成数字。
常见的检查时异常:
ClassNotFoundException:类没有被发现异常。 SQLException:数据库相关异常 IOException:IO操作异常 ParseException:解析错误异常 FileNotFoundException:文件未发现异常。
当 catch 后面的参数和发生的异常类型不匹配时,捕获异常失败,程序会终止,并由系统抛出异常提示。
可以采用多重 catch ,分别对不同类型的异常进行处理,类似于 if - else if。
把有可能产生异常的代码放到try中,catch负责匹配并处理异常,finally块用于进行收尾工作(关闭数据库、关闭文件、释放内存等资源),不管是否发生异常,finally内的代码都将执行。只有一种情况下不执行 finally 内的代码:在 try 或 catch 内部用 System.exit(0); 退出 JVM,finally 将没机会执行。
可以省略掉 catch,捕获到异常之后不对异常进行任何处理,直接进入 finally。
若有 return 关键字在 try - catch - fianlly 内部,系统的执行顺序总是执行到 return 的前一句, 接着执行完 finally 内部代码后再 return,不管 return 是存在于 try 还是 catch。
当一个方法可能存在异常,而此时自身又无法更好的处理,可以交给外界处理。此时用throws声明并抛出异常。开发者可以根据需要声明检查时异常(Exception或者非运行时异常)和运行时异常(RuntimeException或其子类)。如果调用处也不知道如何处理异常,可选择继续声明异常,我们把这个过程称为异常上抛,继续 throws。
方法的重载完全不会受到声明异常的影响,若类中某一方法声明了异常,其重载的方法声不声明异常都可以。
但是重写不一样,以下四种情况都是合法的:
除了系统自动抛出异常外,有些问题需要开发者手动抛出异常。使用关键字 throw
1 public void setGender(String gender) throws Exception{
2 if(gender.equals("男") || gender.equals("女")) {
3 this.gender = gender;
4 }else {
5 throw new Exception("性别不合法!");
6 }
7 }
如果开发者需要手动抛出的异常在系统不存在,可以自定义异常。如果要自定义异常,首先要确定异常类型,如果异常是运行时异常,必须继承 RuntimeException 或其子类;如果异常是检查时异常,必须继承 Exception 或其子类。异常的命名方式,参考系统命名方式,以Exception结尾。
1 public class AgeException extends Exception{
2
3 public AgeException() {
4 super();
5 }
6
7 public AgeException(String message) {
8 super(message);
9 }
10 }
给定一个仅包含大小写字母和空格 ' '
的字符串,返回其最后一个单词的长度。如果不存在最后一个单词,请返回 0 。
说明:一个单词是指由字母组成,但不包含任何空格的字符串。
示例:
输入: "Hello World" 输出: 5
源码:
1 class Solution {
2 public int lengthOfLastWord(String s) {
3 int num = 0;
4 for(int i = s.length() - 1; i >= 0; i--){
5 if (s.charAt(i) == ' ' && num == 0)
6 continue;
7 if (s.charAt(i) != ' ')
8 num++;
9 else
10 break;
11 }
12 return num;
13 }
14 }