前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内部类、异常以及 LeetCode 每日一题

内部类、异常以及 LeetCode 每日一题

作者头像
Carlos Ouyang
发布2019-08-19 17:00:21
6920
发布2019-08-19 17:00:21
举报
文章被收录于专栏:Java 学习日记Java 学习日记

1 内部类

内部类的作用:

  • 内部类提供了更好的封装,可以把内部类隐藏于外部类之内,不允许同一个包中的其他类访问该类。(例如给“牛”这个类组合一个“牛腿”,则可以把牛腿定义成内部类,因为牛腿脱离了牛没有意义)
  • 内部类成员可以直接访问外部类私有数据,因为内部类被当成其外部类成员。
  • 匿名内部类适合用于创建仅需要使用一次的类。

内部类除了必须定义在其他类里面之外,还有如下区别:

  • 内部类可以比外部类多使用三个修饰符:private 、protected 、static (被当作成员)
  • 非静态内部类不能拥有静态成员。

成员内部类(方法外,外部类里面定义的)的 class 文件的格式是 OuterClass$InnerClass.class。

1.1 非静态内部类

当调用非静态内部类的实例方法时,必须有一个非静态内部类实例,而非静态内部类实例必须寄生在外部类实例里。

  • 非静态内部类方法访问某个变量时:优先在方法内寻找局部变量;接着在内部类找;接着在外部类找;如果依然不存在,则编译错误,提示找不到改变量。如果外部类成员变量、内部类成员变量、局部变量同名,则可以用 外部类名.this.val、this.val、val 来区分。
  • 如果外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问其实例成员。
  • 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。
  • 非静态内部类里不能有静态方法、静态成员变量、静态代码块。(可以有普通初始化块)
1.1.1 创建非静态内部类实例
  • 在外部类中,可以直接按照普通的创建对象的形式创建内部类实例
  • 在其它类中,需要先创建外部类实例,再通过外部类实例创建内部类实例,内部类实例寄生于外部类实例。
代码语言:javascript
复制
1 OuterClass outer = new OuterClass();
2 (OuterClass.)InnerClass inner = outer.new Inner();
3 或
4 (OuterClass.)InnerClass inner = new OuterClass().new Inner(); 

1.2 静态内部类

使用 static 来修饰一个内部类,则这个内部类就属于外部类本身。静态内部类可以包含静态成员,也可以包含非静态成员,但是静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

静态内部类是外部类的一个静态成员,因此外部类的所有方法、所有初始化块中可以使用静态内部类来定义变量、创建对象。

外部类依然不能直接访问静态内部类的成员,但可以通过类名(或对象)作为调用者访问静态内部类的成员。

PS Java 还允许在接口里定义内部类,接口里的内部类默认是 public static 修饰

1.2.1 创建静态内部类实例

  • 在外部类中,可以直接按照普通的创建对象的形式创建内部类实例
  • 其他类中:
代码语言:javascript
复制
1 (OuterClass.)InerClass iner = new (OuterClass.)InnerClass();

1.3 局部内部类

声明周期和所在方法相同,生成 class 文件 格式为:OuterClass$NInnerClass.class。对比成员内部类,多了一个数字(N),因为同一个类了里可能有两个以上同名的局部内部类。

局部内部类若访问了局部变量(方法中定义的),则会自动给改变量加上 final 修饰符,意味着不能修改局部变量的值。

1.4 匿名内部类

适合创建只需要使用一次的类,定义格式如下:

代码语言:javascript
复制
1 new 实现接口()|父类构造器(实参列表){
2 //类体
3 }

匿名内部类必须继承一个父类,或实现一个接口,且最多继承一个父类或实现一个接口。

规则:

  • 匿名内部类不能是抽象类
  • 不能定义构造器,但可以定义初始化块,来完成构造器的工作。

当通过实现接口创建匿名内部类时,括号里不能有参数;

当通过继承父类来创建匿名内部类时,将拥有和父类相似的父类构造器(相同的形参列表),会根据参数列表调用父类构造器。类体里可以重写父类的普通方法。

同样的匿名内部类访问局部变量时,会自动添加 final 修饰。

2 异常处理

2.1 异常

异常是指在程序的运行过程中所发生的不正常的情况,它会中断正在运行的程序。java中通过异常处理机制为程序提供异常处理的能力,保持程序继续运行而不中断!

涉及异常处理的常用关键字有:try、catch、finally、throws、throw

2.2 try - catch

把有可能产生异常的代码放到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。

2.3 try - catch - finally

把有可能产生异常的代码放到try中,catch负责匹配并处理异常,finally块用于进行收尾工作(关闭数据库、关闭文件、释放内存等资源),不管是否发生异常,finally内的代码都将执行。只有一种情况下不执行 finally 内的代码:在 try 或 catch 内部用 System.exit(0); 退出 JVM,finally 将没机会执行。

可以省略掉 catch,捕获到异常之后不对异常进行任何处理,直接进入 finally。

若有 return 关键字在 try - catch - fianlly 内部,系统的执行顺序总是执行到 return 的前一句, 接着执行完 finally 内部代码后再 return,不管 return 是存在于 try 还是 catch。

2.4 声明异常

2.4.1 throws 关键字

当一个方法可能存在异常,而此时自身又无法更好的处理,可以交给外界处理。此时用throws声明并抛出异常。开发者可以根据需要声明检查时异常(Exception或者非运行时异常)和运行时异常(RuntimeException或其子类)。如果调用处也不知道如何处理异常,可选择继续声明异常,我们把这个过程称为异常上抛,继续 throws。

2.4.2 声明异常与方法重载、重写

方法的重载完全不会受到声明异常的影响,若类中某一方法声明了异常,其重载的方法声不声明异常都可以。

但是重写不一样,以下四种情况都是合法的:

  1. 父类方法声明了异常(检测时或运行时),子类可以不声明任何异常。
  2. 父类方法声明没有声明任何异常(检测时或运行时),子类不声明异常或者声明运行时异常。(不能声明检测时异常)
  3. 父类声明了异常(检测时或运行时),子类声明完全一样的异常。
  4. 父类声明了检测时异常,子类声明了运行时异常。

2.5 手动抛出异常

除了系统自动抛出异常外,有些问题需要开发者手动抛出异常。使用关键字 throw

代码语言:javascript
复制
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 }

2.6 自定义异常

如果开发者需要手动抛出的异常在系统不存在,可以自定义异常。如果要自定义异常,首先要确定异常类型,如果异常是运行时异常,必须继承 RuntimeException 或其子类;如果异常是检查时异常,必须继承 Exception 或其子类。异常的命名方式,参考系统命名方式,以Exception结尾。

代码语言:javascript
复制
 1 public class AgeException extends Exception{
 2 
 3     public AgeException() {
 4         super();
 5     }
 6 
 7     public AgeException(String message) {
 8         super(message);
 9     }
10 }

3 LeetCode

58. 最后一个单词的长度

给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。如果不存在最后一个单词,请返回 0 。

说明:一个单词是指由字母组成,但不包含任何空格的字符串。

示例:

输入: "Hello World" 输出: 5

源码:

代码语言:javascript
复制
 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 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-04-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 内部类
    • 1.1 非静态内部类
      • 1.1.1 创建非静态内部类实例
    • 1.2 静态内部类
      • 1.3 局部内部类
        • 1.4 匿名内部类
        • 2 异常处理
          • 2.1 异常
            • 2.2 try - catch
              • 2.3 try - catch - finally
                • 2.4 声明异常
                  • 2.4.1 throws 关键字
                  • 2.4.2 声明异常与方法重载、重写
                • 2.5 手动抛出异常
                  • 2.6 自定义异常
                  • 3 LeetCode
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档