黑马程序员_JAVA笔记09—面向对象5(内部类、异常)

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

1、内部类
        访问规则:
                内部类可以直接访问外部类中的成员,包括私有,之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
                外部类要访问内部类,必须建立内部类对象。

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

当内部类在成员位置上,就可以被成员修饰符所修饰
比如,private,将内部类在外部类中进行封装。
           static,内部类就具备static的特性。当内部类被static修饰后,只能访问外部类中的static成员,不能访问非static成员,出现了访问局限。
            在外部其他类中,如何直接访问static内部类。

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

class Outer
{
        int x=8;
         int y=3;
         static class Inter1//定义静态内部类
        {
                void function1()//定义非静态函数
                {
                }
                static void function2()//定义静态函数
                {
                }
        }
        class Inter//内部类可以被private修饰
        {
                 int y = 4;
                void function()
                {
                         int y = 5;
                        System.out.println(y);//y=5
                        System.out.println(this.y);// y = 4
                        System.out.println(Outer.this.y);//y=3
                         System.out.println(x);//内部类可以直接访问外部类成员,x前省略了Outer.this
                }
        }
        void method()
        {
                Inter in = new Inter();//创建内部类对象,访问内部类方法
                in.function();
        }
}
class InterOuterDemo
{
        public static void main(String[] args)
        {
                 Outer ou = new Outer();
                ou.mehod();

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

                 //    访问外部类中静态内部类中的非静态函数
                new Outer.Inter1().function1();
                //   访问外部类中静态内部类中的静态函数
                Outer.Inter.function2();
        }
}

2、当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容
class Body
{
        private class xinZang
        {

        }
        public void show()
        {
                new xinZang();
        }
}

3、匿名内部类,其实就是内部类的简写格式。定义匿名内部类的前提,内部类必须是继承一个类或者实现接口
      注意:  只有内部类定义在成员位置上时,才能被private或static修饰。若定义在局部,则不能被static修饰。
        内部类定义在局部时,不可以被成员修饰符所修饰;可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能被final修饰的局部变量
class Outer
{
        int x= 3;
        void method()//若void method(final int z),此时才可以被Inner访问
        {        
                //方法内的内部类访问放发的局部变量
               final  int y = 5;//此时y必须被定义为final
                class Inner
                {
                        void function()
                        {
                                System.out.println(Outer.this.x);
                                 System.out.println(y);//y被定义为final才能被访问,
                                 System.out.println(z);
                         }
                }
                new Inner().function();
        }
}

匿名内部类代码:一般情况
abstract class AbsDemo
{
        abstract void show();
}
class Outer
{
        int x= 3;
         class Inner extends AbsDemo
        {
                void method()
                {
                        System.out.println(x);
                }
        }
        public void function()
        {
            new Inner().method();
        }
}

改为匿名内部类
abstract class AbsDemo
{
        abstract void show();
}
class Outer
{
        int x= 3;
     
        public void function()
        {
                //红色代码是一个整体,是一个对象,是类AbsDemo的子类对象,是上文绿色部分的简写。
                new AbsDemo()
                {
                        void show()
                        {
                                 System.out.println(x);
                        }
                        void  show1()//也可以定义其他方法,调用时.show()该为.show1(),但不能同时调用(.show().show1())
                        {

                        }
                } .show()//红色代码是对象,.show()表示调用方法show()


                  new AbsDemo()
                {
                        void show()
                        {
                                 System.out.println(x);
                        }
                        void  show1()//也可以定义其他方法,调用时.show()该为.show1(),但不能同时调用(.show().show1())
                        {

                        }
                }.show1()//调用方法show1()
            /*另一种方法,给该对象起名字
                AbsDemo abc = new AbsDemo()
                   {
                        void show()
                        {
                                 System.out.println(x);
                        }
                        void  show1()
                        {
                        }
                }
                abc.show();
                abc.show1();//不可以,因为多态,abc只能调用父类中定义过的
                */
        }
}

匿名内部类格式:   new 父类 或者接口(){定义子类的内容}
其实;匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。一般匿名内部类中定义的方法最好不要超过三个,因为匿名内部类就是为了简化代码的。

当用方法参数为接口类型时,可以定义一个匿名内部类传进方法。

public static void show(Inter in)
{
        in.method();
}

public static void main(String[] args)
{
         show(new Inter()
        {
            public void method()
            {
                    System.out.println("method run");
            }
        });
]

另一个示例,创建object子类对象,用匿名内部类
class InnerTest
{
        public static void main(String[] args)
        {
                 new Object()
                {
                        public void function()
                        {
                                System.out.println("dfdf");
                        }
                }.function();
        }
}

4、异常,就是程序在运行时出现不正常情况。
    异常由来:问题也是现实生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
    问题的划分:
            严重问题,java通过Error类进行描述。对于Error一般不编写针对性的代码对其进行处理 。
            非严重问题,java通过Exception类进行描述。可以使用针对性的处理方式进行处理。
    无论Error或者Exception都有一些共性内容,比如不正常情况的信息、引发原因等。将这些共性内容进行抽取,形成类Throwable,而类Error  Exception是它的子类

5、异常处理,java提供了特有的语句进行处理,基本格式如下:
    try
    {
            需要被检测的代码:
     }
    catch(异常类  变量)
    {
            处理一号仓的代码:处理方式
    }
    finally
    {
            一定会执行的语句
    }




示例:
class Demo
{
        int div(int a,int b)
        {
                return a/b;
        }
}

class ExceptionDemo
{
        public static void main(String[] args)
        {
                Demo d = new Demo();
                try
                {
                       System.out.println( d.div(3,0));//此时会出现异常
                }
                catch(Exception e)//创建对象接收问题对象
                {
                        System.out.println("除以零");
                          System.out.println(e.getMassage());//获取异常信息
                         System.out.println(e.toString());//异常名称、异常信息
                         e.printStackTrace();//打印堆栈中的异常名称、信息、出现位置
                        //其实jvm默认的异常处理机制,就是在调用printStackTrace()打
                    //印异常在堆栈中的跟踪信息
                }
                System.out.println("over");
        }
}
异常处理流程:
        当d.div(3,0)时,出现了问题。
        该问题所属的异常类将该问题封装成一个对象,new AritchmenticException()
        将该问题丢给调用d.div(3,0)的函数,即main函数。
        此时因为有try,就检测到了这个问题对象。
        try将该问题对象丢给catch,catch中定义的Exception e  对象,用来接收这个问题对象。即Exception e  = new ArithcmenticException();
        catch接收完问题对象后,执行catch的语句进行处理。

6、throws关键字
class Demo
{
        int div(int a,int b)  throws Exception//在功能上通过throws关键字声明
                                                                    //了该功能有可能会出现问题
        {
                return a/b;
        }
}
class ExceptionDemo
{
        public static void main(String[] args)// throws Exception   方式二抛异常
        {
                Demo d = new Demo();
                 //方式一:对异常进行捕捉
                  try
                {
                int x = d.div(4,1)
                System.out.println( x);
                }
                cach(Exception e)
                {
                        e.printStackTrace();
                }
                System.out.println("over");
        }
}
throws  理解:当方法声明来了 throw Exception,表示该方法可能出现问题,而且强制要求后面应用到该方法的程序必须进行处理这个异常,通常有两种处理方法,一个是try cantch 进行捕捉,二是同样抛出异常,即throw Exception。若不处理则编译出错。不过一般情况不抛异常,而是进行捕捉

7、对多异常的处理(注意:程序中出现异常,但没处理,则程序终止)
        声明异常时,建议声明更为具体的异常,这样处理的可以更具体。抛出几个异常,在try catch中就有几个catch,每个catch处理一个异常,更有针对性。(但是,可以写一个catch(Exception e),因为多态性,这里e可以接受一切异常,如果这样的话就不具备针对性,容易忽略一些不可预料的异常,如果一定要写则要放在所有catch的最后面);如果多个catch块中的异常出现继承关系,父类异常catch要放在最下面。
        注意:建议在进行catch处理时,catch中一定要定义具体处理方式,不要简单定义句e.printStackTrace(),也不要简单的就书写一条输出语句。
class Demo
{
        int div(int a,int b)  throws ArithmeticException.ArrayIndexOutOfBoundsException
        {
                int[] arr = new int[a];
                System.out.println (arr[4]);
                return a/b;
        }
}
class ExceptionDemo
{
        public static void main(String[] args)
        {
                Demo d = new Demo();
                 try
                {
                int x = d.div(4,1)
                System.out.println( x);
                }
                cach(ArithmeticException e)
                {
                        e.printStackTrace();
                }
                catch(ArrayIndexOutOfBoundsException e)
                {
                        e.printStackTrace();
                }
                System.out.println("over");
        }
}

8、自定义异常 ,因为项目中会出现一些特有的问题,而这些问题并未被java所描述并封装对象,所以对于这些特有问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。
    当在函数内部出现了throw抛出异常对象,那么就必须给出对应的处理动作。一是在内部try catch   二是在函数上声明让调用者处理
    一般情况下函数内出现异常,函数上需要声明。
    因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。
    自定义异常:必须是自定义类继承Exception。
    
    继承Exception原因:异常体系有一个特点,因为异常类和异常对象都需要被抛出。他们都具备可抛性,这个可抛性是Throwable这个体系的独有特点,只有这个体系中的类和对象才可以被throw和throws操作。

需求:在本程序中,对于除数是负数,也视为是错误的,那么就需要对这个问题进行自定义异常。
class FuShuException extends Exception
{
        /*
         因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。
        FuShuException(String msg)
        {
                super(msg);
        }


        */
        private String msg;
        FuShuException(String msg)
        {
                this.msg = msg;
        }
        public String getMessage()//重写父类Exception中的方法getMessage
        {
                return msg;
        }
}
class Demo
{
    int div(int a ,int b) throws FuShuException//一般情况下函数内出现异常,函数上需要声明。
    {
        if(b<0)
        {
             throw new FuShuException();//手动通过throw抛出一个自定义异常对象
        }
        return a/b;
    }
}
class ExceptionDemo
{
        public static void main(String[] args)
        {
                Demo d = new Demo();
                 try
                {
                int x = d.div(4,1)
                System.out.println( x);
                }
                cach(FuShuException e)
                {
                        System.out.println("出现负数了");
                }
                System.out.println("over");
        }
}

9、throws与throw的区别
        一:throws使用在函数上,throw使用在函数内。
        二:throws后面跟的是异常类,可以是多个,用逗号分开;throw后面跟的是异常对象

10、RunTimeException,  Exception中一个非常特殊的子类异常,运行时异常。    如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过。

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

class Person
{
        public void checkName(String name)
        {
             //    if("lise".equals(name)    该方法可以避免空指针异常
            //    if(name!=null&&name.equals("lise") 该方法可以避免空指针异常
                if(name.equals("lise")/ /NullPointerException
                        System.out.println("yes");
                else
                        System.out.println("no");
        }
}
class PersonDemo
{
        public static void main(String[] args)
        {
                Person p = new Person();
                p.checkName( null);
        }
}


自定义异常时,如果该异常的发生,无法再继续进行运算,就让自定义异常继承RunTimeException.

对于异常分两种:
    一:编译时被检测的异常,非运行时异常,该异常必须被声明,需要调用者去处理,表示该异常可以被处理。
    二:编译时不被检测的异常(运行时异常,RunTimeException,及其子类),该异常表示如果出现了异常,那么程序就无法进行下去了,必须修改代码。

注意:throw异常时,程序已经终止,因此throw后面的语句都执行不到。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值