Java内部类和异常类的概念以及使用

1 内部类

Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类成为内部类的外嵌类。

内部类的类体中不可以声明类变量和类方法。外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员。

内部类的使用规则:
(1)声明内部类如同在类中声明方法或变量一样,一个类把内部类看作是自己的成员。
(2)外嵌类的类体中可以用内部类声明的对象,作为外嵌类的成员。
(3)外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。
(4)内部类的类体中不可以声明类变量和方法。
(5)外嵌类和内部类在编译时,生成两个.class文件。

例如:某种类型的农场饲养了一种特殊种类的牛,但不希望其他农场饲养这种特殊种类的牛,那么这种类型的农场就可以将创建这种特殊种牛的类作为自己的内部类。
下面的例子1(Example1.1.java)中有一个RedCowForm(红牛农场)类,该类中有一个名字为RedCow (红牛)的内部类。

RedCowForm.java

public class RedCowForm {
    static String formName;
    RedCow cow;  //内部类声明对象

    RedCowForm() {
    }

    RedCowForm(String s) {
        cow = new RedCow(150, 112, 5000);
        formName = s;
    }

    public void showCowMess() {
        cow.speak();
    }

    class RedCow {  //内部类的声明
        String cowName = "红牛";
        int height, weight, price;

        RedCow(int h, int w, int p) {
            height = h;
            weight = w;
            price = p;
        }

        void speak() {
            System.out.println("偶是" + cowName + ",身高:" + height + "cm 体重:" + weight + "kg,生活在" + formName);
        }
    }    //内部类结束
}
115526523

Example1.1.java

public class Example1_1 {
    public static void main(String[] args) {
        RedCowForm form = new RedCowForm("红牛农场");
        form.showCowMess();
        form.cow.speak();
    }
}

需要特别注意的是,Java编译器生成的内部类的字节码文件的名字和通常的类不同,内部类对应的字节码文件的名字格式是“外嵌类名$ 内部类名”,例如,例子1中内部类的字节码文件是RedCowForm$RedCow.class。因此,当需要把字节码文件复制给其他开发人员时,不要忘记了内部类的字节码文件。
内部类可以被修饰为static 内部类,例如,例子1中的内部类声明可以是static classRedCow。类是一种数据类型,那么static内部类就是外嵌类中的一-种静 态数据类型,这样一来,程序就可以在其他类中使用static内部类来创建对象了。但需要注意的是,static 内部类不能操作外嵌类中的实例成员变量。

假如将例子1中的内部类RedCow更改成static内部类,就可以在例子1的Example1_ 1
主类的main方法中增加如下的代码。

RedCowForm.RedCow redCow = new RedCowForm.RedCow(180,119,6000);
        redCow.speak();

注意:非内部类不可以是static类

2 匿名类

2.1 和子类有关的匿名类

创建子类对象时,除了使用父类的构造方法外还有类体,此类体被认为是一个子类去掉类声明后的类体,称作匿名类。

假设Bank是类,那么下列代码就是用Bank的一个子类(匿名类)创建对象:

new Bank() {
	匿名类的类体
};

和子类有关的匿名类:
(1)匿名类是一个子类,由于无名可用,所以不可能用匿名类声明对象,但却可以直接用匿名类创建一个对象。
(2)匿名类可以继承父类的方法也可以重写父类的方法。
(3)使用匿名类时,必然是在某个类中直接用匿名类创建对象,以此,匿名类一定是内部类。
(4)匿名类可以访问外嵌类中的成员变量和方法,匿名类的类体中不可以声明static成员变量和static方法。
(5)由于匿名类是一个子类,但没有类名,所以在用匿名类创建对象时,要直接使用父类的构造方法。

例子2:该类共有4个类: (Example2_1. java)、ShowBoard类、
OutputAlphabet类型、 OutputEnglish. java 。该匿名类的对象负责输出希腊字母表。

OutputAlphabet.java

abstract class OutputAlphabet {
    public abstract void output();
}

OutputAlphabet .java

public class OutputEnglish extends OutputAlphabet { //输出英文字母子类
    public void output(){
        for (char c='a';c<='z';c++){
            System.out.printf("%3c",c);
        }
    }
}

ShowBoard .java

public class ShowBoard {
    void showMess(OutputAlphabet show) { //参数show是OutputAlphabet类型的对象
        show.output();
    }
}

Example2_1.java

public class Example2_1 {
    public static void main(String[] args) {
        ShowBoard board = new ShowBoard();
        board.showMess(new OutputEnglish());//向参数传递OutputAlphabet的子类OutputEnglish的对象

        board.showMess(new OutputAlphabet() {   //向参数传递OutputAlphabet的匿名子类的对象
            @Override
            public void output() {
                for (char c = 'α'; c <= 'ω'; c++)  //输出希腊字母
                    System.out.printf("%3c", c);
            }
        });//分号在这里
    }
}

2.2 和接口有关的匿名类

和接口有关的匿名类
假设Computable是一个接口,那么,Java允许直接用接口名和一个类体创建一个匿名对象,此类体被认为是实现了Computable接口的类去掉类声明后的类体,称作匿名类。

下列代码就是用实现了Computable接口的类(匿名类)创建对象:

new Computable(){
	实现接口的匿名类的类体
};

下面例子演示了和接口有关的匿名类的用法:

interface SpeakHello {
    void speak();
}

class HelloMachine {
    public void turnOn(SpeakHello hello) {
        hello.speak();
    }
}

public class Example7_3 {
    public static void main(String[] args) {
        HelloMachine machine = new HelloMachine();
        machine.turnOn(new SpeakHello() {
            @Override
            public void speak() {
                System.out.println("hello,you are welcome!");
            }
        });
        machine.turnOn(new SpeakHello() {
            @Override
            public void speak() {
                System.out.println("你好,欢迎光临!");
            }
        });
    }
}

3 异常类

所谓异常就是程序运行时可能出现一些错误,比如试图打开一个根本不存在的文件等,异常处理将会改变程序的控制流程,让程序有机会对错误作出处理。程序运行出现异常时,Java运行环境就用异常类Exception的相应子类创建一个异常对象,并等待处理。异常对象可以调用如下方法得到或输出有关异常的信息:

异常对象可以调用如下方法得到或输出有关异常的信息:

public String getMessage();
public void printStackTrace();
public String toString();

3.1 try-catch语句

Java使用try-catch语句来处理异常,将可能出现的异常操作放在try-catch语句的try部分,将发生异常后的处理放在catch部分。
try-catch语句的格式如下:

try{
	包含可能发生异常的语句
}
catch(ExceptionSubClass1 e){
	...
}
catch(ExceptionSubClass2 e){
	...
}

下面一个例子给出了try-catch语句的用法:

public class Example3_1 {
    public static void main(String[] args) {
        int n = 0, m = 0, t = 1000;

        try {
            m = Integer.parseInt("8888");
            n = Integer.parseInt("ab89"); //发生异常,转向catch
            t = 7777;  //t没有机会被赋值
        } catch (NumberFormatException e) {
            System.out.println("发生异常:" + e.getMessage());
        }
        System.out.println("n=" + n + ",m=" + m + ",t=" + t);

        try {
            System.out.println("故意抛出I/O异常!");
            throw new java.io.IOException("我是故意的");
            //System.out.println("这个输出语句肯定没有机会执行,所以必须注释掉,否则编译出错");
        } catch (java.io.IOException e) {
            System.out.println("发生异常:" + e.getMessage());
        }
    }
}

带finally子语句的try~catch语句,语法格式如下:

try{ }
catch(ExceptionSubClass e){ }
finally{}

其执行机制是在执行try~catch语句后,执行finally 子语句,也就是说,无论在try部分是否发生过异常,finally 子语句都会被执行

3.2 自定义异常类

(1)一个方法不处理它产生的异常,而是沿着调用层次向上传递,由调用它的方法来处理这些异常,叫声明异常.

声明异常的方法:
在产生异常的方法名后面加上要抛出(throws)的异常的列表:

如: void compute(int x) throwsAri thmeticException
{//这里有异常发生,但是并没有处理…}

(2)我们也可以扩展Exception类定义自己的异常类,然后规定哪些方法产生这样的异常。一个方法在声明时可以使用throws关键字声明要产生的若干个异常,并在该方法的方法体中具体给出产生异常的操
作,即用相应的异常类创建对象,并使用throw关键字抛出该异常对象,导致该方法结束执行。

(3)通常情况下,计算两个整数之和的方法不应当有任何异常放出,但是,对某些特殊应程序,可能不允许同号的整数做求和运算,比如当一个整数代表收入,一个整数代表支出时,这两个整数就不能是同号。

例子 (Example3_2. java)中,Bank类中有一个income(int in, int out)方法,对象调用该方法时,必须向参数in传递正整数、向参数out传递负数,并且int+out必须大于等于0,否则该方法就抛出异常( BankException. java )。因此,Bank类在声明income(int in, int out)方法时,使用throws关键字声明要产生的异常。

BankException.java

public class BankException extends Exception {
    String message;

    public BankException(int m, int n) {
        message = "入账资金" + m + "是负数或支出" + n + "是正数,不符合系统要求.";
    }

    public String warnMess() {
        return message;
    }
}

Bank.java

public class Bank {
    private int money;

    public void income(int in, int out) throws BankException {
        if (in <= 0 || out >= 0 || in + out <= 0) {
            throw new BankException(in, out); //方法抛出异常,导致方法结束
        }
        int netIncome = in + out;
        System.out.printf("本次计算出的纯收入是:%d元\n", netIncome);
        money = money + netIncome;
    }

    public int getMoney() {
        return money;
    }
}

Example3_2.java

public class Example3_2 {
    public static void main(String[] args) {
        Bank bank = new Bank();
        try {
            bank.income(200, -100);
            bank.income(300, -100);
            bank.income(400, -100);
            System.out.printf("银行目前有%d元\n", bank.getMoney());
            bank.income(200, 100);
            bank.income(99999, -100);
        } catch (BankException e) {
            System.out.println("计算收益的过程出现如下问题:");
            System.out.println(e.warnMess());
        }
        System.out.printf("银行目前有%d元\n", bank.getMoney());
    }
}

4 断言

断言语句用于调试代码阶段。在调试代码阶段让断言语句发挥作用,这样就可以发现一些致命的错误,当程序正式运行时就可以关闭断言语句,但仍把断言语句保留在源代码中,如果以后应用程又需要调试,可以重新启用断言语句。

使用关键字assert声明一条断言语句,断言语句有以下两种格式:

assert booleanExpression;

assert booleanExpression:messagelException;

启用与关闭断言语句
当使用Java解释器直接运行应用程序时,默认地关闭断言语句,在调试程序时可以使用-ea启用断言语句,例如:
java -ea mainClass

例子4中,使用一个数组放着某学生5门课程的成绩,程序准备计算学生的成绩的总和。在调试程序时使用了断言语句,如果发现成绩有负数,程序立刻结束执行。程序调试开启断言语句运行效果如图4.1,关闭断言语句运行效果如图4.2。

import java.util.Scanner;
public class Example4 {
  public static void main (String args[ ]) {
       int [] score={-120,98,89,120,99};
       int sum=0;
       for(int number:score) {
          assert number>0:"负数不能是成绩";
          sum=sum+number;
       }
       System.out.println("总成绩:"+sum);
   }
}

图4.1

图4.2

5 综合案例

下面的例子5中模拟向货船上装载集装箱,如果货船超重,那么货船认为这是一个异常将拒绝装载集装箱,但无论是否发生异常,货船都需要正点启航

DangerException.java

public class DangerException extends Exception {
    final String message = "超重";
    public String warnMess() {
        return message;
    }
}

CargoBoat.java

public class CargoBoat {
    int realContent;  //装载的重量
    int maxContent;   //最大装载量
    public void setMaxContent(int c) {
        maxContent = c;
    }
    public void loading(int m) throws DangerException {
        realContent += m;
        if(realContent>maxContent) {
            throw new DangerException();
        }
        System.out.println("目前装载了"+realContent+"吨货物");
    }
}

Example5.java

public class Example5 {
    public static void main(String[] args) {
        CargoBoat ship = new CargoBoat();
        ship.setMaxContent(1000);
        int m =600;
        try{
            ship.loading(m);
            m = 400;
            ship.loading(m);
            m = 367;
            ship.loading(m);
            m = 555;
            ship.loading(m);
        }
        catch(DangerException e) {
            System.out.println(e.warnMess());
            System.out.println("无法再装载重量是"+m+"吨的集装箱");
        }
        finally {
            System.out.printf("货船将正点启航");
        }
    }
}

到此这篇关于Java内部类和异常类的概念以及使用的文章就介绍到这了,更多相关java类的使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java类加载机制、类加载器、自定义类加载器的案例

    类加载机制 java类从被加载到JVM到卸载出JVM,整个生命周期包括:加载(Loading).验证(Verification).准备(Preparation).解析(Resolution).初始化(Initialization).使用(using).和卸载(Unloading)七个阶段. 其中验证.准备和解析三个部分统称为连接(Linking). 1.加载 加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Clas

  • java类成员中的访问级别浅析

    我们知道想要访问一个网站,根据身份的不同,会有一些使用上的限制,这就是权限级别的体现.在java的类成员中,有一些访问的级别是需要我们了解的,主要分为四种:public.private.protected.package.下面我们就这四种访问修饰符分别进行详细的介绍. 一.四种访问修饰符 1.public修饰符用于暴露域和方法,以便在类定义的包外部能访问它们.对包和类中必要的接口元素,也需要使用这个级别:main()方法必须是public的,toString()方法也必须是public的.一般不

  • 源码解析Java类加载器

    参考内容: 深入理解Java虚拟机(JVM高级特性与最佳实践) --周志明老师 尚硅谷深入理解JVM教学视频--宋红康老师 我们都知道Java的类加载器结构为下图所示(JDK8及之前,JDK9进行了模块化): 关于三层类加载器.双亲委派机制,本文不再板书,读者可自行百度. 那么在JDK的源码中,三层结构的具体实现是怎么样的呢? Bootstrap ClassLoader(引导类加载器) 引导类加载器是由C++实现的,并非Java代码实现,所以在Java代码中是无法获取到该类加载器的. 一般大家都

  • 两种实现Java类隔离加载的方法

    阿里妹导读:Java 开发中,如果不同的 jar 包依赖了某些通用 jar 包的版本不一样,运行时就会因为加载的类跟预期不符合导致报错.如何避免这种情况呢?本文通过分析 jar 包产生冲突的原因及类隔离的实现原理,分享两种实现自定义类加载器的方法. 一  什么是类隔离技术 只要你 Java 代码写的足够多,就一定会出现这种情况:系统新引入了一个中间件的 jar 包,编译的时候一切正常,一运行就报错:java.lang.NoSuchMethodError,然后就哼哧哼哧的开始找解决方法,最后在几百

  • 利用json2POJO with Lombok 插件自动生成java类的操作

    前言 很多时候,我们定义接口或者调用别人的接口时,手里只有一份接口文档,文档中提供一段示例json格式的报文,我们需要根据json中的字段,挨个去定义java POJO 的字段属性. 属实费劲,且有时候万一手抖,个别字段填错了,就导致前后端联调不能一次性成功. 如果能有办法将json直接生成java POJO,岂不是能省去很多时间. 1.安装idea 插件 打开preferences → Plugins → marketplace → 输入:json2Pojo with Lombok,点击安装并

  • java类实现日期的时间差的实例讲解

    我们在对不同时间的间隔上,如果是同一天的时间计算,尚且是可以手动算一下.如果加上日期的条件限制,那么手动的计算会比较困难.但是在java中我们调用类来进行解决,这样能节约不少的使用,也不容易计算失误.下面我们就Period.Duration.ChronoUnit类的计算方法带来介绍. 1.Period类 方法getYears(),getMonths()和getDays() import java.time.LocalDate;import java.time.Month;import java.

  • Java内部类和异常类的概念以及使用

    1 内部类 Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类成为内部类的外嵌类. 内部类的类体中不可以声明类变量和类方法.外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员. 内部类的使用规则: (1)声明内部类如同在类中声明方法或变量一样,一个类把内部类看作是自己的成员. (2)外嵌类的类体中可以用内部类声明的对象,作为外嵌类的成员. (3)外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法. (4)内部类的类体中不可以声明类变量和方法. (5

  • 详解Java内部类与对象的打印概念和流程

    目录 一.内部类的概念 二.内部类的分类 三.成员内部类 1.普通内部类 2.静态内部类 四.局部内部类 五.对象的打印 一.内部类的概念 在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类.内部类也是封装的一种体现. public class OutClass {//外部类 class InnerClass{//内部类 } } 注意事项: 1.内部类一定是定义在class 类名{}之中的类,定义在class 类名{}之外的,哪怕是在一份文件中,也并不

  • JAVA中常见异常类

    1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片未经初始化,或者图片创建时的路径错误等等.对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了.数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,

  • java 内部类(匿名类,匿名对象,静态内部类)详解及实例

    内部类的介绍 定义在另外一个类中的类,叫内部类 成员内部类 1..new 创建成员内部类必须先创建外部类的实例,然后通过.new 创建内部类的对象 2..this 可以通过外部类的类名.this去访问外部类的所有属性和方法. public class Test1 { String name = "asnd"; public static void main(String[] args) { Test1 test1 = new Test1(); Inner mInner = test1.

  • 深入探讨JAVA中的异常与错误处理

    异常与错误: 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误: 它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务).

  • 全面了解Java中的内部类和匿名类

    Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦.学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地设计你的程序结构.下面从以下几个方面来介绍: 第一次见面 public interface Contents { int value(); } public interface

  • 详解Java 中的嵌套类与内部类

    详解Java 中的嵌套类与内部类 在Java中,可以在一个类内部定义另一个类,这种类称为嵌套类(nested class).嵌套类有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类较少使用,非静态嵌套类使用较多,也就是常说的内部类.其中内部类又分为三种类型: 1.在外部类中直接定义的内部类. 2.在函数中定义的内部类. 3.匿名内部类. 对于这几种类型的访问规则, 示例程序如下: package lxg; //定义外部类 public class OuterClass { //外部类静态成员变量

  • Java面向对象程序设计:类的定义,静态变量,成员变量,构造函数,封装与私有,this概念与用法详解

    本文实例讲述了Java面向对象程序设计:类的定义,静态变量,成员变量,构造函数,封装与私有,this概念与用法.分享给大家供大家参考,具体如下: 本文内容: 什么是面对对象 类的定义与对象实例化 成员变量 成员变量的有效范围 成员变量的赋值 静态变量.方法与实例变量.方法 构造函数 封装与私有 this关键字 注:函数和方法是一样东西.[由于我之前学习的时候有些书籍不是同样的说法,书看多了,我就习惯了不同情况下用不同的说法] 首发时间:2018-03-22 什么是面对对象: 面向对象强调行为处于

  • Java多线程基础——Lock类

    之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized一样的功能,并且还提供了Condition来显示线程间通信. Lock类是Java类来提供的功能,丰富的api使得Lock类的同步功能比synchronized的同步更强大.本文章的所有代码均在Lock类例子的代码 本文主要介绍一下内容: Lock类 Lock类其他功能 Condition类 Con

  • java 内部类的实例详解

    java 内部类的实例详解 可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类. public class OuterClass { private String name ; private int age; public String getName() { return name; } p

随机推荐