Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类成为内部类的外嵌类。
例如:某种类型的农场饲养了一种特殊种类的牛,但不希望其他农场饲养这种特殊种类的牛,那么这种类型的农场就可以将创建这种特殊种牛的类作为自己的内部类。
public class RedCowForm{
static String formName;
RedCow cow;//内部类声明对象
public 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;
public RedCow(int h,int w,int p) {
height=h;
weight=w;
price=p;
}
void speak(){
System.out.println("偶是"+cowName+"身高:"+height+"cm 体重:"+weight+"kg,生活在"+formName);
}
}//内部类结束
}// 外嵌类结束
public class exma {
public static void main(String[] args) {
RedCowForm form=new RedCowForm("红牛农场");
form.showCowMess();
form.cow.speak();
}
}
外嵌类的类体中可以用内部类声明的对象,作为外嵌类的成员。
外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。
内部类的类体中不可以声明类变量和方法。
外嵌类和内部类在编译时,生成两个.class文件。
Java允许我们直接使用一个类的子类的类体创建一个子类对象。
1、和子类有关的匿名类(此子类并非继承的子类)
创建子类对象时,除了使用父类的构造方法外还有类体,此类体被认为是一个子类去掉类声明后的类体,称作匿名类。
假设Bank是类,那么下列代码就是用Bank的一个子类(匿名类)创建对象:
new Bank{
匿名类的类体
}
如下例
abstract class OutputAlphabet {
public abstract void output();
}
public class OutputEnglish extends OutputAlphabet { //输出英文字母的子类
public void output(){
for(char c='a';c<='z';c++){
System.out.printf("%3c",c);
}
}
}
public class ShowBoard {
void showMess(OutputAlphabet show){ //参数show是OutputAlphabet类型的对象
show.output();
}
}
public class Exam {
public static void main(String[] args) {
ShowBoard borad=new ShowBoard();
borad.showMess(new OutputEnglish());//向参数传递OutputAlphabet的子类OutputEnglish对象
borad.showMess(new OutputAlphabet() {
public void output() { //参数传递OutputAlphabet的匿名子类对象
for(char c='a';c<='z';c++){
System.out.printf("%3c",c);
}
}
}
);
}
}
2、和接口有关的匿名类
假设Computable是一个接口,那么,Java允许直接用接口名和一个类体创建一个匿名对象,此类体被认为是实现了Computable接口的类去掉类声明后的类体,称作匿名类。
下列代码就是用实现了Computable接口的类(匿名类)创建对象:
new Computable(){
实现接口的匿名类的类体
};
例
interface SpeakHello{
void speak();
}
class HelloMachine{
public void turnOn(SpeakHello hello) {
hello.speak();
}
}
public class Exam {
public static void main(String[] args) {
HelloMachine machine=new HelloMachine();
machine.turnOn(new SpeakHello() { //和接口SpeakHello有关的匿名类
public void speak() {
System.out.println("hello,you are welcome!");
}
}
);
machine.turnOn(new SpeakHello() { //和接口SpeakHello有关的匿名类
public void speak() {
System.out.println("你好,欢迎光临");
}
}
);
}
}
所谓异常就是程序运行时可能出现一些错误,比如试图打开一个根本不存在的文件等,异常处理将会改变程序的控制流程,让程序有机会对错误作出处理。程序运行出现异常时,Java运行环境就用异常类Exception的相应子类创建一个异常对象,并等待处理。
异常对象可以调用如下方法得到或输出有关异常的信息:
public String getMessage();
public void printStackTrace();
public String toString();
Java使用trycatch语句来处理异常,将可能出现的异常操作放在trycatch语句的try部分,将发生异常后的处理放在catch部分。
try~catch语句的格式如下:
try {
包含可能发生异常的语句
}
catch(ExceptionSubClass1 e) {
…
}
catch(ExceptionSubClass2 e) {
…
}
import java.util.jar.JarException;
public class exam {
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子语句都会被执行。
例
public class DangerException extends Exception {
final String message="超重";
public String warnMess() {
return message;
}
}
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){
realContent-=m;
throw new DangerException();
}
System.out.println("目前装载了"+realContent+"吨货物");
}
}
public class Exam {
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=347;
ship.loading(m);
m=555;
ship.loading(m);
}
catch (DangerException e) {
System.out.println(e.warnMess());
System.out.println("无法再装载重量是"+m+"吨的集装箱");
}
finally{
System.out.println("货物将正点启航");
}
}
}
一个方法不处理它产生的异常,而是沿着调用层次向上传递,由调用它的方法来处理这些异常,叫声明异常.
声明异常的方法:在产生异常的方法名后面加上要抛出(throws)的异常的列表:
如:void compute(int x) throws ArithmeticException
{//这里有异常发生,但是并没有处理…}
如上例
我们也可以扩展Exception类定义自己的异常类,然后规定哪些方法产生这样的异常。
一个方法在声明时可以使用throws关键字声明要产生的若干个异常,并在该方法的方法体中具体给出产生异常的操作,即用相应的异常类创建对象,并使用throw关键字抛出该异常对象,导致该方法结束执行。
自定义异常类例题
public class BankException extends Exception {
String message;
public BankException(int m,int n) {
message="入账资金"+m+"是负数或支出"+n+"是正数,不符合系统要求";
}
public String warnMess() {
return message;
}
}
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;
}
}
public class Exam {
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());
}
}
断言语句用于调试代码阶段。在调试代码阶段让断言语句发挥作用,这样就可以发现一些致命的错误,当程序正式运行时就可以关闭断言语句,但仍把断言语句保留在源代码中,如果以后应用程又需要调试,可以重新启用断言语句。
使用关键字assert声明一条断言语句,断言语句有以下两种格式:
assert booleanExpression;
assert booleanExpression:messageException
例
import java.util.*;
public class exam {
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);
}
}
Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类成为内部类的外嵌类。
和某类有关的匿名类就是该类的一个子类,该子类没有明显的用类声明来定义,所以称做匿名类。
和某接口有关的匿名类就是实现该接口的一个类,该子类没有明显的用类声明来定义,所以称做匿名类。
Java使用trycatch语句来处理异常,将可能出现的异常操作放在trycatch语句的try部分,当try部分中的某个方法调用发生异常后,try部分将立刻结束执行,而转向执行相应的catch部分。