黑马程序员——>第九天<面向对象(内部类-匿名内部类-异常)>

-------android培训java培训、期待与您交流-------

01面向对象(内部类访问规则)
将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)
/*
内部类的访问规则:
1,内部类可以直接访问外部类中的成员,包括私有。
 之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this        System.out.println("innner :"+Outer.this.x);
2,外部类要访问内部类,必须建立内部类对象。
*/

class Outer
{
 private int x = 3; //外部成员

 
   private class Inner//内部类 可以被私有修饰,当内部类在外部类的成员位置上时机可以
 {
  //int x = 4;  // 内部成员
  void function()
  {
   //int x = 6;    //内部局部成员
   System.out.println("innner :"+Outer.this.x);   //x是3
                     //System.out.println("innner :"+x); // x是6  内部有的不出去找
                   //System.out.println("innner :"+this.x);   // x是4
  }
 }

 /**/
 void method()
 {
  Inner in = new Inner();   //外部访问内部
  in.function();
 }
}


class  InnerClassDemo
{
 public static void main(String[] args) 
 {
  Outer out = new Outer();
  out.method();

  //直接访问内部类中的成员。
//  Outer.Inner in = new Outer().new Inner();
//  in.function();
 }
}

 

02面向对象(静态内部类)
访问格式:

1,当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。
可以直接建立内部类对象。
格式
 外部类名.内部类名  变量名 = 外部类对象.内部类对象;
 Outer.Inner in = new Outer().new Inner();

2,当内部类在成员位置上,就可以被成员修饰符所修饰。
 比如,private:将内部类在外部类中进行封装。
  static:内部类就具备static的特性。
  当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
   如果类中数据几乎都静态,他也静态,不涉及特有数据,全是共享数据
  在外部其他类中,如何直接访问static内部类的非静态成员呢?
  new Outer.Inner().function(); new一个内部类对象调用function方法

  在外部其他类中,如何直接访问static内部类的静态成员呢?
  outer.Inner.function();

 注意:当内部类中定义了静态成员,该内部类必须是static的。
    当外部类中的静态方法访问内部类时,内部类也必须是static的。

 

 
当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物的内容。

 

 

 

*/

class Outer
{
 private static  int x = 3;

 
 static class Inner//静态内部类
 {
  static void function()
  {
   System.out.println("innner :"+x);
  }
 }

 static class Inner2
 {
  void show()
  {
   System.out.println("inner2 show");
  }
 }

 public static void method()
 {
  //Inner.function();
  new Inner2().show();
 }

}


class  InnerClassDemo2
{
 public static void main(String[] args) 
 {
  Outer.method();
  //Outer.Inner.function();
  //new Outer.Inner().function();
  //直接访问内部类中的成员。
//  Outer.Inner in = new Outer().new Inner();
//  in.function();
 }
}


 

03面向对象(内部类定义原则)

当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物的内容。

class Body         一般用于程序设计上
{
 private class XinZang
 {

 }

 public void show()
 {
  new XinZang().
 }
 
}
当这类事物直接访问外部事物中的内容时,就把这个事物定义在里边,这样定义,代码的设计是最优的。


04面向对象(匿名内部类)

内部类可以写在类的任意位置上 成员也包括局部
/*
内部类定义在局部时,
1,不可以被成员修饰符修饰  局部内部类不可以定义静态成员
2,可以直接访问外部类中的成员,因为还持有外部类中的引用。
 但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
*/

class Outer
{
 int x = 3;

 void method(final int a)
 {
  final int y = 4;   //但是不可以访问它所在的局部中的变量。
  class Inner   // 局部内部类
  {
   void function()    //非静态,没对象,不运行。
   {
    System.out.println(y);
   }
  }
 
  new Inner().function(); // 建立对象后才能运行
  
 }
}


class  InnerClassDemo3
{
 public static void main(String[] args) 
 {
  //new Outer().method();

                Outer out = new Outer();
                out.method(7);
  out.method(8);
 //当调用method方法,就进栈了,一进栈,栈里边有一个a,把7赋给a,就锁住了,7一直为a。method方法执行完,就出栈释放了,再调用就又进栈了,就是一个新的a
 }

}


 

 


/* 
匿名内部类:
1,匿名内部类其实就是内部类的简写格式。
2,定义匿名内部类的前提:
 内部类必须是继承一个类或者实现接口。
3,匿名内部类的格式:  new 父类或者接口(){定义子类的内容}
4,其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。 可以理解为带内容的对象。
5,匿名内部类中定义的方法最好不要超过3个。不包含3,最好是两个或一个
  方法多   搞一个类继承一下,用类进行封装,下面建立类的对象进行调用

弊端:不能直接调用自己的方法;不能进行强制转换动作;方法过多不要使用匿名内部类(会导致阅读性非常差)

class Inner extends AbsDemo       
 {
  
  void show()       
  {
   System.out.println("show :"+x);
  }
        }


 


下面是上面的简化格式

public void function()
{
               //new Inner().show();
             new AbsDemo()  // absdemo的匿名子类对象 其实就是将上面一句话中的Inner()给替换了
  {
   
   void show()
   {
    System.out.println("x="+x);
   }
                }.show();  // 所以可以直接.show()进行调用 ( absdemo的匿名子类对象) 
}



 

 class Inner extends AbsDemo       // 继承了一个类
 {
  int num = 90;
  void show()       /进行了覆写
  {
   System.out.println("show :"+num);
  }
  void abc()
  {
   System.out.println("hehe");
  }
 }


 public void function()
 {
                //new Inner().show();   //创建对象 进行调用
  //AbsDemo a = new Inner();
//  Inner in = new Inner();
//  in.show();
//  in.abc();



分析:内部类都做了什么事情
 继承了一个类
 进行了覆写
 创建对象
 进行调用
 

 
                   匿名内部类
            下面的是absdemo的子类对象(因为只有子类才能覆写absdemo类中的抽象方法)
  AbsDemo d = new AbsDemo()                  //后面跟{}表示将AbsDemo中的方法实现了
                                                                    // 父类引用指向子类对象(多态)
  {
   int num = 9;   //成员变量
                                   // 一般不会在匿名内部类中写太复杂,是因为匿名内部类是为了简化而存在的,你写太复杂 就失去意义了

   void show()
   {
    System.out.println("num==="+num);
   }
   void abc()
   {
    System.out.println("haha");
   }
  };

  d.show();              //只能使用父类方法
  //d.abc();//编译失败;  父类中没定义过  abc是子类方法
     匿名对象对方法只能调用一次
写匿名函数是为了简化书写,覆盖方法
 

 

05面向对象(异常概述)
异常的由来:
用面向对象的思想把问题进行描述,并对其进行了对象的封装
把问题封装成对象就是异常
异常的体系
 Throwable
  Error
    通常出现重大问题如:运行的类不存在或者内存溢出等
  Exception
    在运行时运行出现的一些情况,可以通过try catch finally
Exception和Error的子类名都是以父类名作为后缀

Java在设计异常体系时,将容易出现的情况都封装成了对象。

/*
异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。
   其实就是java对不正常情况进行描述后的对象体现。

对于问题的划分:两种:一种是严重的问题,一种非严重的问题。

对于严重的,java通过Error类进行描述。
 对于Error一般不编写针对性的代码对其进行处理。

对与非严重的,java通过Exception类进行描述。
 对于Exception可以使用针对性的处理方式进行处理。

无论Error或者Exception都具有一些共性内容。
比如:不正常情况的信息,引发原因等。

Throwable
 |--Error
 |--Exception
在使用一个体系时:原则,看父类定义建立子类对象

06面向对象(异常try-catch)

异常的处理

java 提供了特有的语句进行处理。
try
{
 需要被检测的代码;
}
catch(异常类 变量)
{
 处理异常的代码;(处理方式)
}
finally
{
 一定会执行的语句;
}


对捕获到的异常对象进行常见方法操作。
 String getMessage():获取异常信息。
*/

class Demo
{
 int div(int a,int b)throws Exception//在功能上通过throws的关键字声明了该功能有可能会出现问题。
 {
  return a/b;
 }
}

class  ExceptionDemo1
{
 public static void main(String[] args) //throws Exception
 {
  Demo d = new Demo();
  try
  {
   int x = d.div(4,0);
   System.out.println("x="+x);
  }
  catch (Exception e)  //Exception e = new ArithmeticException();  多态
  {
                        System.out.println("除零啦"); 
   System.out.println(e.getMessage()); //by zero
                        System.out.println(e.toString());   //异常名称:异常信息
  }
  e.printStackTrace();//异常名称,异常信息,异常出现的位置
//其实jvm默认的异常处理机制,就是在调用printStackTrace方法,打印异常的堆栈的跟踪信息。

  System.out.println("over");

 }
}


 

07面向对象(异常声明throws)
异常的基本处理方式

在函数上声明异常。
便于提高安全性,让调用者进行处理。不处理编译失败。


 

当调用了一个有问题的功能时有几种处理方式: 要么捕捉,要么抛出去!
 
有问题时要给出预先处理方式

08面向对象(多异常处理)

对多异常的处理。

1,声明异常时,建议声明更为具体的异常。这样处理的可以更具体。
2,对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。
 如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。


建议在进行catch处理时,catch中一定要定义具体处理方式。
不要简单定义一句 e.printStackTrace(),
也不要简单的就书写一条输出语句。


*/

class Demo
{
 int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
 {

  int[] arr = new int[a];

  System.out.println(arr[4]);

  return a/b;
 }
}
//声明几个异常,就要有几个针对性处理

class  ExceptionDemo2
{
 public static void main(String[] args) //throws Exception
 {
  Demo d = new Demo();
  try
  {
   int x = d.div(5,0);
   System.out.println("x="+x);
  }
  
  catch(Exception e)
  {
   System.out.println("hahah:"+e.toString())//;它全能干的原因是多态性:不管你抛什么异常,都是我小弟,都能帮你搞定,但是,处理没有针对性。所以在写try catch时要写针对性处理,向下面那样
  }
  catch (ArithmeticException e)
  {
   System.out.println(e.toString());
   System.out.println("被零除了!!");

  }
  catch (ArrayIndexOutOfBoundsException e)
  {
   System.out.println(e.toString());
   System.out.println("角标越界啦!!");
  }
  //异常不能同时发生:函数中只要有异常发生,这个函数就已经结束了。异常一产生,就被try检测到了,然后找到对应的catch进行了处理
System.out.println("over");

 }
}

当发生两个异常以外的异常时,你如果又写了catch(Exception e),1.你的处理并不具体,也就是说你自己都不知道具体发生什么了,你就把这个问题给处理了,相当于将问题隐藏,而程序还在继续运行。如果出现了对方指定的问题以外的情况,这时应该做的是程序停掉。让我们能看到这个问题,以致导致的现象,才能把代码进行修正,将问题解决掉,或者将问题在功能上标示一下,让对方有更针对性的处理。2.如果你将catch(Exception e)写在所有的catch最上面,程序第一个执行它,下面的就不执行了。在真出现异常时,我们是不打印的。把这个问题用一个硬盘文件记录下来 ,称之为异常日志文件(每天都会产生的文件,记录着程序每天运行的状况),管理人员或者网站的维护人员会经常去看日志,然后进行调试

09面向对象(自定义异常)/*因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想。将特有的问题。进行自定义的异常封装。

自定义异常。

需求:在本程序中,对于除数是-1,也视为是错误的是无法进行运算的。那么就需要对这个问题进行自定义的描述。*/

class FuShuException extends Exception //getMessage();
{
 private int value;

 FuShuException()
 {
  super();
 }
 FuShuException(String msg,int value)
 {
  super(msg);
  this.value = value;
 }

 public int getValue()
 {
  return value;
 }

}
class Demo
{
 int div(int a,int b)throws FuShuException
 {
  if(b<0)
   throw new FuShuException("出现了除数是负数的情况------ / by fushu",b);//手动通过throw关键字抛出一个自定义异常对象。

  return a/b;
 }
}
class  ExceptionDemo3
{
 public static void main(String[] args) 
 {
  Demo d = new Demo();
  try
  {
   int x = d.div(4,-9);
   System.out.println("x="+x);  
  }
  catch (FuShuException e)
  {
   System.out.println(e.toString());
   //System.out.println("除数出现负数了");
   System.out.println("错误的负数是:"+e.getValue());
  }
  System.out.println("over");

 }
}


 

/*
当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
要么在内部try catch处理。
要么在函数上声明让调用者处理。

一般情况下,函数内出现异常,函数上需要声明。


发现打印的结果中只有异常的名称,却没有异常的信息。
因为自定义的异常并未定义信息。

如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息传递给父类通过super语句。
那么就可以直接通过getMessage方法获取自定义的异常信息。

 

自定义异常:
必须是自定义类继承Exception。


继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。

只有这个体系中的类和对象才可以被throws和throw操作。

父类中的写法:

class Throwable
{
 private String message;
 Throwable(String message)
 {
  this.message = message;
 }

 public String getMessage()
 {
  return message;
 }
}

class Exception extends Throwable
{
 Exception(String message)
 {
  super(message);
 }
}



父类当中已经定义了构造函数可以接收一个信息,并通过方法获取信息,那么毫无疑问,里边必须要有一个变量来记录这个信息(String message)。那么,父类把这些信息都做完了,子类在继承时就不用再进行这些动作了,只要将信息传给父类(super(message;)),然后子类new Exception("haha").getMessage();就可以获取这些信息。

class Person
{
 String name;
 Person(String name)
 {
  this.name = name;
 }
 public String getName()
 {
  return name;
  }
}

class Student extends Person
{
 Student (String name)
 {
  super(name);
 }
}

new Sttdent("lisi").getName();


 

 


10面向对象(throw和throws的区别)

throws和throw的区别
throws使用在函数上。
throw使用在函数内。

throws后面跟的异常类。可以跟多个。用逗号隔开。
throw后跟的是异常对象。
11面向对象(runtimeException)

Exceptoin中有一个特殊的子类异常RuntimeException 运行时异常。

如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。

如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过;

之所以不用在函数声明,是因为不需要让调用者处理。
当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,
对代码进行修正。

 


自定义异常时:如果该异常的发生,无法在继续进行运算,
就让自定义异常继承RuntimeException。

RuntimeException的出现会引发程序停止
对于异常分两种:
1,编译时被检测的异常。
  在javac编译时,会去检测如果方法当中抛出了非RuntimeException以及其子类(因为这些异常时可处理的,要标示出去,让调用者去处理),那么在函数上没标示就视为有安全隐患
  如果函数上标示了异常,调用者也必须要有相对应的处理方式:要么抛,要么try
2,编译时不被检测的异常(运行时异常。RuntimeException以及其子类)
    里边抛,外面不用声明:凡是RuntimeException以及其子类,它会判断一下,如果是这个类型,就不管

 

12面向对象(异常练习)

/*
毕老师用电脑上课。

开始思考上课中出现的问题。


比如问题是
 电脑蓝屏。
 电脑冒烟。

要对问题进行描述,封装成对象。


可是当冒烟发生后,出现讲课进度无法继续。

出现了讲师的问题:课时计划无法完成。


*/

class LanPingException extends Exception
{
 LanPingException(String message)
 {
  super(message);
 }
}

class MaoYanException extends Exception
{
 MaoYanException(String message)
 {
  super(message);
 }
}


class NoPlanException extends Exception
{
 NoPlanException(String msg)
 {
  super(msg);
 }
}

class Computer
{
 private int state = 3;
 public void run()throws LanPingException,MaoYanException
 {
  if(state==2)
   throw new LanPingException("蓝屏了");
  if(state==3)
   throw new MaoYanException("冒烟了");

  System.out.println("电脑运行");
 }
 public void reset()
 {
  state = 1;
  System.out.println("电脑重启");
  
 }
}

class Teacher
{
 private String name;
 private Computer cmpt;

 Teacher(String name)
 {
  this.name = name;
  cmpt = new Computer();

 }

 public void prelect()throws NoPlanException
 {
  try
  {
   cmpt.run();   
  }
  catch (LanPingException e)
  {
   cmpt.reset();
  }
  catch (MaoYanException e)
  {
   
   test();
   throw new NoPlanException("课时无法继续"+e.getMessage());
   throw单独存在时,下面不要写语句,因为它就是函数的结束标示(return)
                   所以test();要放在throw上面
  }
  System.out.println("讲课");
 }
 public void test()
 {
  System.out.println("练习");
 }

}

 

class ExceptionTest 
{
 public static void main(String[] args) 
 {
  Teacher t = new Teacher("毕老师");
  try
  {
   t.prelect();
  }
  catch (NoPlanException e)
  {
   System.out.println(e.toString());
   System.out.println("换老师或者放假");
  }
  
 }
}



 

 

-------android培训java培训、期待与您交流-------



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值