Java基础-09-面向对象(续4)

Java基础-面向对象

面向对象进阶(续)

1、面向对象(内部类访问规则)

内部类:将一个类定义在另一个类里面,类里面的那个类就称为内部类(内置类、嵌套类) 访问特点:

(1)、内部类可以直接访问外部类中成员,包括私有成员。
(2)、而外部类要访问内部类中的成员必须要建立内部类的对象。

Eg:

public class Outer
{
    int x = 3;//即使加上private,内部类一样可以访问
    void method()
    {
        Inner in = new Inner ();
        in.function();
        //System.out.println(x);
    }
    class Inner         //内部类
    {
        int x = 4 ; 
        void function()
        {
            int x = 5;
            System.out.println("Inner:"+x+this.x+Outer.this.x);
        }
    }
}
class InnerClassDemo
{
    public static void main(String []args)
    {
        /*
        Outer out = new Outer();
        out.method();
        */
        //下面代码替换以上代码,效果一样。
        Outer.Inner in = new Outer().new Inner();
        in.function();
        //要明白,之所以可以直接访问外部类的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
    }
}

程序结果:Inner:543

2、面向对象(静态内部类)

访问格式

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

(2)、当内部类在成员位置上,就可以被成员修饰符所修饰。比如:内部类具备static的特性。 Eg:

class Outer
{
    private int x = 3 ; 
    static class Inner //静态类
    {
        void function()
        {
            System.out.println("inner:"+x);        //错误,静态内部类不能访问外部类的成员,除非外部类成员也是静态的。
        }
    }
}
class OuterClassDemo
{
    public static void main(String[]args)
    {
        Outer.Inner in = new Outer().new Inner();
        in.function();
    }
}

//编译失败 静态内部类知识点总结:

(1)、当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
(2)、在外部其他类中,如何直接访问静态内部类的非静态成员呢?
在主类主函数中{new Outer.Inner().function();}
(3)、在外部其他类中,如何直接访问静态内部类的静态成员呢?
在主类主函数中{new Outer.Inner.function();}
注意:当内部类中定义了静态成员,该内部类必须是static的。否则编译失败。
(4)、当外部类中的静态方法访问内部类是,内部类也必须是static的。

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

当描述事物时,事物内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容。 例如这样:

class body
{
    private class heart
    {}
    public void show()
    {
        new heart();
    }
}

4、面向对象(匿名内部类)

Eg:

class Outer 
{
    int x = 3 ; 
    void method(final int a)
    {
        final int y = 4 ;
        class Inner 
        {
            void function()
            {
                System.out.println(a);
            }
        }
        new Inner().function();    
    }
}
class InnerClassDemo
{
    public static void main(String []args)
    {
        Outer out = new Outer();
        out.method(7);
        out.method(8);
    }
}

内部类定义在局部时:

(1)、不可以被成员修饰符修饰。
(2)、可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

匿名内部类:

(1)、匿名内部类,其实就是内部类的简写格式。
(2)、定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
(3)、匿名内部类格式:new 父类或者接口(){定义子类的内容}
(4)、其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖,可以理解为带内容的对象。
(5)、匿名内部类中定义的方法最好不要超过3个。

Eg(没匿名前)

abstract class AbsDemo
{
    abstract void show();
}
class Outer
{
    int x = 3 ; 
    class Inner extends AbsDemo
    {
        void show()    
        {
            System.out.println("show:"+x);
        }
    }
    public void function()
    {
        new Inner().show();
    }
}
class InnerClassDemo
{
    public static void main(String []args)
    {
        new Outer().function();
    }
}

//输出结果:show:3

Eg2(有匿名后):

abstract class AbsDemo
{
    abstract void show();
}
class Outer
{
    int x = 3 ; 
    /*
    class Inner extends AbsDemo
    {
        void show()    
        {
            System.out.println("show:"+x);
        }
    }
    */
    public void function()
    {
        //new Inner().show();
        new AbsDemo()
        {
            void show()
            {
                System.out.println("show:"+x);
            }
        }.show();        //该部分就是注释掉部分的简写。
    }
}
class InnerClassDemo
{
    public static void main(String []args)
    {
        new Outer().function();
    }
}

输出结果:show:3

//一道匿名内部类的练习。

interface Inter
{
    void method();

}
class Test
{
    //补足代码,通过匿名内部类
    /*这注释部分是用来提示
     * static class Inner implements Inter
     * {
     *      public void method()
     *      {
     *          System.out.println("method run");
     *      }
     * }
     */
    //以下是补充的代码!
    static Inter function()         //静态的Inter类类型的function方法
    {
        return new Inter() //匿名内部类
        {
            public void method()
            {
                System.out.println("method run");
            }
        };

    }
}
class InnerClassTest
{
    public static void main(String[]args)
    {
        //由该段代码推断出以上需补足的代码!
        Test.function().method();
    }
}

上面代码我们这样入手:

(1)、Test.function():这段代码可以推断出Test类中有一个静态的方法function。
(2)、method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象。因为只有是Inter类型的对象,才可以调用method方法。

结合上面两点:

Test.function().method();
相当于
Inter in = Test.function();

in.method();

5、面向对象(异常概述)

异常:就是程序在运行时出现的不正常情况。

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

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

对于严重的问题:Java通过Error类来描述,而对于Error,一般不编写针对性代码对其进行处理。

对于非严重的问题:Java通过Exception类进行描述,这类可以使用针对性的处理方式进行处理。

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

体系:

Throwable 
      |--Error
      |--Exception

6、面向对象(异常try-catch)

异常的处理: java提供了特有的语句进行处理:如下

try
{需要被检测的代码}
catch(异常类 变量)
{处理异常的代码:处理方式}
finally
{一定会执行的语句}

Eg:

class Demo
{
    int div(int a, int b)
    {
        return a/b;
    }
}
class ExceptionDemo
{
    public static void main(String []args)
    {
        Demo d =new Demo();

        try
        {
            int x = d.div(4, 0);//new ArithmeticException
            System.out.println("x="+x);//没执行,而直接转到catch语句中去了
        }
        catch(Exception e)//相当于Exception e = new ArithmeticException();
        {

            System.out.println("除零啦"+"e:"+e.getMessage());//e: / by zero

            e.printStackTrace();
        }
        System.out.println("over");//该句可以被执行到
    }
}

程序结果:

除零啦e:/ by zero
java.lang.ArithmeticException: / by zero
    at day09.Demo.div(Outer.java:7)
    at day09.ExceptionDemo.main(Outer.java:18)
over

在程序中使用到的

  • getMessage()方法是Exception类继承父类Throwable类中方法,返回此 throwable 的详细消息字符串,即获取异常信息。

  • printStackTrace()方法是Exception类的方法,用来返回异常名称,异常信息和异常出现的位置。 其实JVM默认的异常处理机制,就是在调用printStaceTrace方法,打印异常的堆栈的跟踪信息。

7、面向对象(异常声明throws)

上一节的例子中应该要在Demo类中对div方法进行异常声明,如下,这样才不会引起程序崩溃。

class Demo
{
    int div(int a, int b)throws Exception
    /*
     * throws Exception在功能上通过throws的关键字声明了该功能有可能会出现问题
     * */
    {
        return a/b;
    }
}
class ExceptionDemo
{
    public static void main(String []args)
    {
        Demo d =new Demo();

        try
        {
            int x = d.div(4, 0);//new ArithmeticException
            System.out.println("x="+x);//没执行,而直接转到catch语句中去了
        }
        catch(Exception e)
        {

            System.out.println("除零啦"+"e:"+e.getMessage());//e: / by zero
            e.printStackTrace();
        }


        System.out.println("over");//该句可以被执行到
    }
}

8、面向对象(多异常处理)

(1)、在声明异常时,建议声明更为具体的异常,这样处理得更具体些。 例如在方法上进行具体的异常声明throws ArithmeticException后,我们在catch语句中就可以直接定义ArithmeticException异常类的对象进行处理,即catch(ArithmeticException e){处理语句}

(2)、对多异常处理的形式。在可能会出现多异常的方法上进行多异常声明:throws 异常1,异常2,......,然后在catch语句中需要分开进行处理,即

catch(异常1 e)

{处理语句}

catch(异常2 e)

{处理语句}

........

(3)、对方声明了多少个异常,就对应有多少个catch块,不要定义多余的,如果多个catch块中的异常出现继承关系,父类异常所对应的catch块要放在其他catch块的下面,或者最下面。

(4)、建议:在catch处理时,catch中一定要定义具体处理方式,不要简单定义一句e.printStackTrace(),也不要简单地就书写一条输出语句。一般可以把处理中的出错异常信息用日志文件记录。

9、面向对象(自定义异常)

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

自定义异常:需求:在下面程序中,对于除数是-1,也视为是错误的,是用方法进行运算的,那么就需要对这个问题进行自定义描述。当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作,要么在内部try-catch处理,要么在函数上声明让调用者处理,一般情况下,函数内出现异常,函数上需要声明。

class  FuShuException extends Exception
{
}
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="+x);
        }
        catch(FuShuException e)
        {
            System.out.println(e.toString());
            System.out.println("除数出现了负数了");
        }
        System.out.println("over");
    }
}

输出结果:

day09.FuShuException
除数出现了负数了
over

发现打印的结果中只有异常的名称却没有异常的信息,因为自定义的异常并未定义信息。那么如何定义异常信息呢?观察一下代码:

class  FuShuException extends Exception
{
    private String msg;
    FuShuException(String msg)
    {
        this.msg = msg;
    }
    public String getMessage()
    {
        return msg;
    }
    //继承父类Exception并重载了父类中的构造函数和getMessage方法。
}

class Demo
{
    int div(int a , int b )throws FuShuException
    {
        if(b<0)
        {
            throw new FuShuException("出现了除数是负数的情况:/by fushu");  //继承类对父类构造函数进行了重载,因此我们可以在此处输入要定义的异常信息。
        }
        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="+x);
        }
        catch(FuShuException e)
        {
            System.out.println(e.toString());
            System.out.println("除数出现了负数了");
        }
        System.out.println("over");
    }
}

程序输出结果:

day09.FuShuException: 出现了除数是负数的情况:/by fushu
除数出现了负数了
over

但是由于在Java体系中存在这样一个父类:

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

//而Exception又继承了Throwable类,因而有以下代码

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

因此,原来的代码中的class FuShuException extends Exception里的代码改为下面的

class  FuShuException extends Exception
{

    FuShuException(String msg)
    {
        super(msg);
    }
}

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

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

继承Exception类的原因:异常体系有一个特点,因为异常类和异常对象都被抛出,他们都具有可抛性,这个可抛性是Throwable这个体系中独有的特点,只有这个体系中的类和对象才可以被throw和throws操作。

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

throw和throws的区别:

(1)、throws使用在函数上,throw使用在函数内。
(2)、throws后面跟着异常类,可以很多个,用逗号隔开,throw后跟的是异常对象。

11、面向对象(RuntimeException)

Exception中有一个特殊的子类异常RuntimeException运行时异常如果在函数内抛出该异常,函数上可以不用声明,编译一样通过,如果在函数上声明了该异常,调用者可以不同处理编译一样可以通过。之所以不用在函数声明,是因为不需要让调用者处理,当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正。

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

对于异常分为两种:

(1)、编译时被检测到的异常。
(2)、编译时不被检测到的异常:RuntimeException和其子类。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值