东哥java学习Day9-11---Java(继承)

曾山
2023-12-01

4.继承
4.4 子类的实例化过程

子类中所有的构造函数默认都会访问父类中空参数的构造函数,因为每个构造函数的第一行都有一句默认的语句super();

为什么子类实例化的时候要访问父类中的构造函数呢?
那是因为子类继承了父类,获取到了父类中的内容(属性),所以在使用父类内容之前,要先看父类是如何对自己的内容进行初始化的

ps:

1.当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数
2.子类构造函数中如果使用this调用了奔雷构造函数,那么默认的super()就没有了,因为super和this都只能定义在第一行,所以只能有一个,但可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数
3.super语句必须要定义在子类构造函数的第一行,因为父类的初始化动作要先完成
public class FuZi {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();
    }

}

class Fu {
    Fu() {
        super();  
        show();  //调用的是子类的show方法,此时其成员变量num还未进行显示初始化
        return;
    }
    void show() {
        System.out.println("----Fu show -----");
    }
}
class Zi extends Fu{
    int num = 8;
    Zi() {
        super();
        //通过super初始化父类内容时,子类的成员变量并未显示初始化,等super()父类初始化完毕后,才进行子类的成员变量显示初始化
        return;
    }
    void show() {
        System.out.println("----zi show----");
    }
}

总结:

一个对象实例化过程,以Person p = new Person();为例
1.JVM会读取指定的路径下的Person.class文件,并加载进内存,并会加载Person的父类(如果有直接的父类的情况下)
2.在内存中开辟空间,并分配地址
3.并在对象空间中,对对象的属性进行默认初始化
4.调用对应的构造函数进行初始化
5.在构造函数中,第一行会先到调用父类中构造函数进行初始化
6.父类初始化完毕后,再对子类的属性进行显示初始化
7.再进行子类构造函数的特定初始化
8.初始化完毕后,将地址赋值给引用变量

4.5 final关键字

final可以修饰类,方法,变量
final修饰的类不可以被继承
final修饰的方法不可以被覆盖
final修饰的变量是一个常量,只能被赋值一次
为什么要用final修饰变量,其实,在程序中如果一个数据是固定的,那么直接使用这个数据就可以,但是这种阅读性查,所以应该给这个数据起个名称,而且这个变量名称的值不能变化,所以加上final固定
写法规范:常量所有的字母都大写,多个单词,中间用_连接

4.6 抽象类
4.6.1 抽象类概述

抽象定义:抽象就是从多个事物中将共性的,本质的内容抽取出来
例如:狼和狗共性都是犬科,犬科就是抽象出来的概念

抽象类:
 java中可以定义没有方法体的方法,该方法的具体实现有子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类

 抽象方法的由来:
 多个对象具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法
 例如:狼和狗都有吼叫的方法,可是吼叫内容不一样,所以抽象出来的犬科虽然有吼叫功能,但并不明确吼叫的细节

4.6.2.抽象类的特点

抽象类和抽象方法必须用abstract关键字来修饰

抽象方法只有方法声明,没有方法体,定义在抽象类中
格式:修饰符 abstract 返回值类型  函数名(参数列表)

抽象类不可以被实例化,也就是不可以用new创建对象
原因如下:
1.抽象类是具体事务抽取出来的,本身是不具体的,也没有对应的实例,例如:犬科是一个抽象的概念,真正存在的是狼和狗
2.而且抽象类即使创建了对象,调用抽象方法也没有意义
3.抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则改子类也是抽象类
public class AbstractDemo {
    public static void main(String[] args) {
        DemoA demoa = new DemoA();
        demoa.show();
        DemoB demob = new DemoB();
        demob.show();
    }
}
abstract class Demo { //抽象类
    abstract void show();
} 
class DemoA extends Demo {
    void show() {
        System.out.println("demoa show");
    }
}
class DemoB extends Demo {
    void show() {
        System.out.println("demob show");
    }
}

4.6.4抽象类相关问题

抽象类中是否有构造函数----有,用于给子类对象进行初始化
抽象关键字abstract不可以和那些关键字共存--private,static,final
抽象类中可不可以没有抽象方法?
可以,但是很少见,穆迪就是不让个该类创建对象,AWT的适配器对象就是这种类,通常这个类中的方法有方法体,但是却没有内容

抽象类和一般类的区别

相同点:抽象类和一般类都是用于描述事物的,都在内部定义了成员
不同点:
1.一般类有足够的信息描述事物,抽象类描述事物的信息有可能不足
2.一般类中不能定义抽象方法,只能定义非抽象方法
  抽象类中可定义抽象方法,同时也可以定义非抽象方法
3.一般类可以被实例化
  抽象类不可被实例化

抽象类一定是个父类吗-----是的,因为需要子类覆盖其方法后才可以对子类实例化

4.7 接口

当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口
格式:interface()

接口中的成员修饰符是固定的---接口中的成员都是公共的权限
  成员常量  public static final
  成员函数:public abstract
 接口是对外暴露的规则
 接口是程序的功能扩展
ps:
1.虽然抽象类中的全局变量和抽象方法中的修饰符都可以不用写,但是这样阅读性很差,所以,最好写上
2.类与类之间是继承关系,类与接口直接是实现关系
3.接口不可以实例化,能有实现了接口并覆盖了接口中所有的抽象方法的子类实例化,否则这个子类就是一个抽象类
interface Demo4 {
    public static final int NUM = 4;
    public abstract void show1();
    public abstract void show2();   
}
class Demo4Impl implements Demo4 {  //实现
    public void show1() {}
    public void show2() {}
}
public class InterfaceDemo {    
    public static void main(String[] args) {
        Demo4Impl d = new Demo4Impl();
        System.out.println(d.NUM);
        System.out.println(Demo4Impl.NUM);
        System.out.println(Demo4.NUM);      
    }
}
接口的出现将"多继承"通过另一种形式体现出来,即“多实现”
在java中不直接支持多继承,因为会出现调用的不确定性
所以java将多继承机制进行改良,在java中变成了多实现,一个类可以实现多个接口
接口的出现避免了单继承的局限性

一个类在继承另一个类的同时,还可以实现多个接口

抽象类和接口的异同点?

相同点: 都是不断向上抽取而来的
不同点:

  1.抽象类需要被集成,而且只能单继承
    接口类需要被实现,而且可以多实现
  2.抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法
     接口中只能定义抽象方法,必须由子类去实现
  3.抽象类的继承,是is a关系,定义改体系的基本共性内容
    接口的实现是like a关系
public class BookPC {

    public static void main(String[] args) {
        useUSB(new UPan());
    }

    public static void useUSB(USB u){  //接口类型的引用,用于接收接口的子类对象
        if(u != null) {
            u.open();
            u.close();
        }
    }

}
interface USB { //暴露的原则
    public void  open();
    public void close();
}
//实现原则
//这些设备和电脑的耦合性降低了
class UPan implements USB {
    public void open() {
        System.out.println("upan open");
    }
    public void close() {
        System.out.println("upan close");
    }
}

class USBMouse implements USB {
    public void open() {
        System.out.println("USBMouse open");
    }
    public void close() {
        System.out.println("USBMouse close");
    }
}

4.8 多态

多态:某一类事物的多重存在形式
例如:动物中猫,狗
猫这个对象对应的类型应该是猫类型 :猫 x = new 猫()
同时猫也是动物的一种,也可称为动物: 动物 y = new 猫()
动物是猫和狗具体事物中抽取出来的父类型
父类型引用指向了子类对象

多态性简单说就是一个对象对应着不同类型

体现:父类或者接口的引用指向或者接受自己的子类对象
作用:多态的存在提高了程序的扩展性和后期可维护性

 前提:
  1.需要存在继承或者实现关系
  2.需要有覆盖操作
好处
 提高了代码的扩展性,前期定义的代码可以使用后期的内容
弊端

ps:

 instanceof:用于判断对象的具体类型,只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断

多态时,成员的特点

1.成员变量
 编译时:参考引用型变量所属的类中是否有调用的成员变量
 运行时:参考引用型变量所属的类中是否有调用的成员变量
 简单说:编译和运行都参考等号的左边
2.成员函数(非静态)
 编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过。 没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。
3.静态函数
编译时:参考的是对象所属的类中是否有调用的函数。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译和运行看左边。

4.9 内部类

内部类:将一个类定义在另一个类里面,里面的那个类就成为内部类(内置类,嵌套类)
访问特点:
  内部类可以直接访问外部类中的成员,包括私有成员
  而外部类要访问内部类中的成员必须要建立内部类的对象

内部类的位置:

内部类定义在成员位置上,可以被private、static成员修饰符修饰。被static修饰的内部类只能访问外部类中的静态成员。

如果内部类是静态的,内部类成员也是静态的,可不用创建内部类对象,直接调用。
P.S、
1.如果内部类中定义了静态成员,该内部类也必须是静态的!

2.为什么内部类能直接访问外部类中的成员呢?
那是因为内部类持有了外部类的引用,外部类名.this

3.内部类定义在局部位置上,也可以直接访问外部类中的成员。
同时可以访问所在局部中的局部变量,但必须是被final修饰的

匿名内部类

定义:就是内部类的简化写法。
前提:内部类可以继承或实现一个外部类或者接口。
 格式:
 new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
简单理解:
就是建立一个带内容的外部类或者接口的子类匿名对象。

什么时候使用匿名内部类呢?
 通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。

 好处:增强阅读性。

4.10.1 异常的体系

异常:是在运行时期发生的不正常情况。
在java中用类的形式对不正常情况进行了描述和封装对象。描述不正常的情况的类,就称为异常类。 
1. 以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离,提高阅读性。
2. 其实异常就是java通过面向对象的思想将问题封装成了对象,用异常类对其进行描述。
3. 不同的问题用不同的类进行具体的描述。比如角标越界、空指针异常等等。
4. 问题很多,意味着描述的类也很多,将其共性进行向上抽取,形成了异常体系。

不正常情况分成了两大类:

Throwable:无论是error,还是异常、问题,问题发生就应该可以抛出,让调用者知道并处理。
该体系的特点就在于Throwable及其所有的子类都具有可抛性。
可抛性到底指的是什么呢?怎么体现可抛性呢?

其实是通过两个关键字来体现的:throws throw,凡是可以被这两个关键字所操作的类和对象都具备可抛性。
1. 一般不可处理的:Error

  特点:是由jvm抛出的严重性问题。
  这种问题发生,一般不针对性处理,直接修改程序。

2. 可以处理的:Exception
该体系的特点:子类的后缀名都是用其父类名作为后缀,阅读性很强。

Throwable中的方法:
1. getMessage():获取异常信息,返回字符串。
2.  toString():获取异常类名和异常信息,返回字符串。
3.  printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void。
4. printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅。

4.10.2 自定义异常

可以自定义出的问题称为自定义异常。

对于角标为负数的情况,可以用负数角标异常来表示,负数角标这种异常在java中并没有定义过。
那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述,并封装成对象。
这种自定义的问题描述称为自定义异常。

P.S.
如果让一个类成为异常类,必须要继承异常体系,因为只有成为异常体系的子类才有资格具备可抛性,才可以被两个关键字所操作:throws、throw。

自定义类继承Exception或者其子类,通过构造函数定义异常信息。
    Class DemoException extends Exception{
       DemoException(String message){
           super(message);
        }
    }

通过throw将自定义异常抛出。

throws和throw的区别:
      1. throws用于标识函数暴露出的异常类,并且可以抛出多个,用逗号分隔。throw用于抛出异常对象。
      2. thorws用在函数上,后面跟异常类名。throw用在函数内,后面跟异常对象。

定义功能方法时,需要把出现的问题暴露出来让调用者去处理,那么就通过throws在函数上标识。
在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

异常的分类:

1. 编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
   这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
   这样的问题都可以针对性的处理。

2. 编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。
   这种问题的发生,无法让功能继续,运算无法运行,更多是因为调用的原因导致的或者引发了内部状态的改变导致的。
   那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行调整。

    所以自定义异常时,要么继承Exception,要么继承RuntimeException。

P.S.
 RuntimeException是那些可能在Java虚拟机正常运行期间抛出的异常的超类。
 可能在执行方法期间抛出但未被捕获的RuntimeException的任何子类都无需在throws子句中进行声明。

  异常处理的捕捉形式:
  可以对异常进行针对性处理的方式。
  具体格式是:
        try{    
             //需要被检测异常的代码。
         } catch(异常类 变量) //该变量用于接收发生的异常对象{
              //处理异常的代码。
         }finally{
           //一定会执行的代码;
           }

  P.S.
      finally代码块只有一种情况不会被执行,就是在之前执行了System.exit(0)。

    处理过程:
       try中检测到异常会将异常对象传递给catch,catch捕获到异常进行处理。
       finally里通常用来关闭资源。比如:数据库资源,IO资源等。
       需要注意:try是一个独立的代码块,在其中定义的变量只在该变量块中有效。

   如果在try以外继续使用,需要在try外建立引用,在try中对其进行初始化。IO,Socket就会遇到。

异常处理的原则:

 1. 函数内容如果抛出需要检测的异常,那么函数上必须要声明。
     否则,必须在函数内用try/catch捕捉,否则编译失败。
 2. 如果调用到了声明异常的函数,要么try/catch,要么throws,否则编译失败。
 3. 什么时候catch,什么时候throws呢?
     功能内容可以解决,用catch。
     解决不了,用throws告诉调用者,由调用者解决。
 4. 一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性处理。
   内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。

try catch finally 代码块组合特点:
 1. try catch finally
 2. try catch(多个):当没有资源需要释放时,可以不用定义finally。
 3. try finally:异常无法直接catch处理,但是资源必须关闭。

异常的注意事项:
   1. RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明。
   2. 子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。
   3. 如果父类抛出多个异常,那么子类只能抛出父类异常的子集。

简单说:子类覆盖父类只能抛出父类的异常或者子类的子集。
P.S.

如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try。

/*
 * 异常:就是程序在运行时,出现不正常情况
 * 异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象
 *         其实就是java对不正常情况进行描述后的对象体现
 * 对问题的划分:两种:一种是严重的问题,一种非严重的问题
 * 
 * 对于严重的,java通过error类进行描述
 *          对于Error一般不编写针对性的代码对其进行处理
 * 对于非严重的,java通过Exception类进行描述
 *           对于Exception可以使用针对性的处理方法进行处理
 *           
 * 无论Error或者Exception都具有一些共性内容
 * 比如:不正常情况的信息,引发原因等
 * 
 * Throwable
 *    |--Error
 *    |--Exception
 *    
 * 2,异常的处理
 *    java提供了特有的语句进行处理
 *    try {
 *       需要被检测的代码
 *    } catch (异常类  变量) {
 *       处理异常的代码:(处理方法)
 *    } finally {
 *        一定会执行的语句
 *    }
 *    
 * 3.对捕获到的异常对象进行常见方法操作
 *  String getMessage();  //获取异常信息
 *  
 *  在函数上声明异常
 *  便于提高安全性,对抛出异常进行处理,不处理编译失败
 *  
 *  对多异常的处理
 *  1 声明异常时,建议声明更为具体的异常,这样处理的可以更具体
 *  2 对方声明多个异常,就对应有几个catch块,不要定义多余的catch块
 *    如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
 *  
 *  建立在进行catch处理时,catch中一定要定义具体处理方式
 *  不要简单定义一句 e.printStackTrace(),
 *  也不要简单的就写一条输出语句

总结:由此可以看出,e.toString()获取的信息包括异常类型和异常详细消息,而e.getMessage()只是获取了异常的详细消息字符串。  
e的getMessage()和printStackTrace()方法的区别:
e.getMessage(); 只会获得具体的异常名称. 比如说NullPoint 空指针,就告诉你说是空指针... 

e.printStackTrace();会打出详细异常,异常名称,出错位置,便于调试用.. 
一般一个异常至少几十行
 */
public class ExceptionDemo {

    public static void main(String [] args) {
        Demon  d = new Demon();
        try {
            int x = d.div(5, 0);
            System.out.println("x=" + x);
        } catch (ArithmeticException e) {
            System.out.println(e.toString());
            System.out.println("被零除了!!");

        } catch (ArrayIndexOutOfBoundsException e){
            System.out.println(e.toString());
            System.out.println("角标越界啦!!");
        } catch(Exception e) { //Exception e = new ArithmeticException()
              System.out.println("hahahah" + e.toString());
              System.out.println(e.getMessage());  //by zero
            //  一个exception的getmessage方法将会返回这个e的整个异常链中第一个message不为null的message:-)
         //e的上一层异常通过getRootCause可以得到
              System.out.println(e.toString());//异常名称:异常信息
              e.printStackTrace();//异常名称,异常信息,异常出现的位置
                                   //其实jvm默认的异常处理机制,就是在调用printStackTrace方法。
                                   //打印异常的堆栈的跟踪信息
        }
        System.out.println("over");

    }

}
class Demon {
    int div(int a, int b) throws ArithmeticException,ArrayIndexOutOfBoundsException { //在功能上通过throws的关键字声明了该功能有可能出现的问题
        int[] arr = new int[a];
        System.out.println(arr[4]);
        return a/b;
    }
当try语句中出现异常是时,会执行catch中的语句,java运行时系统会自动将catch括号中的Exception e 初始化,也就是实例化Exception类型的对象。e是此对象引用名称。然后e(引用)会自动调用Exception类中指定的方法,也就出现了e.printStackTrace() ;。 
printStackTrace()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因。
/*
 * 因为项目中会有一些特有的问题,而这些问题并未被java所描述并封装对象
 * 所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,惊醒自定义的异常封装
 * 
 * 自定义异常
 * 需求:在本程序中,对于除数是-1,也视为是错误的是无法进行运算的那么就要对这个问题进行自定义的描述
 * 
 * 当在函数内部出现了throw抛出异常对象,那么就必须给对应的处理动作
 * 要么在内部try catch处理
 * 要么在函数上声明让调用者处理
 * 
 * 一般情况在,函数内出现异常,函数上需要声明
 * 
 * 发现打印的结果中只有异常的名称,却没有异常信息,因为自定义的异常并未定义信息
 * 
 * 如何定义异常信息呢?
 * 因为父类中已经把异常信息的操作都完成了
 * 所以子类只需要在构造时,将异常信息传递给父类通过super语句
 * 那么就可以直接通过getMessage方法获取自定义的异常信息
 * 
 * 自定义异常:必须是自定义类继承Exception
 * 
 * 继承Exception原因:
 * 异常体系有一个特点:因为异常类和异常对象都被抛出
 * 他们都具备可抛性,这个可抛性是Throwable这个体系中独有特点
 * 
 * 只有这个体系中的类和对象才可以被throws和throw操作
 * 
 * throws和throw的区别
 * throws使用在函数上
 * throw使用在函数内
 * 
 * throws后面跟的异常类,可以跟多个,用逗号隔开
 * throw后面跟的是异常对象
 * 
 * 
 * Exception有个特殊的子类异常RuntimeException运行时异常
 * 如果在函数内抛出该异常,函数上可以不用声明,编译一样通过
 * 
 * 如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过
 * 
 * 之所以不用在函数声明,是因为不需要让调用者处理
 * 当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正
 * 
 * 自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException
 *对于异常分两种
   1.编译时,别检测的异常,
   2.编译时,不被检测的异常(运行时异常,RuntimeException及其子类)
/*
    finally代码块:定义一定执行的代码。
    通常用于关闭资源。
注意:
1,finally中定义的通常是 关闭资源代码。因为资源必须释放。
2,finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。
记住一点:catch是用于处理异常。如果没有catch就代表异常没有被处理过,如果该异常是检测时异常。那么必须声明。


异常在子父类覆盖中的体现;
1,子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2,如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3,如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
    如果子类方法发生了异常。就必须要进行try处理。绝对不能抛。


*/

class FuShuException extends Exception {
    private int value;
    FuShuException() {
        super();
    } 
    FuShuException(String msg, int value) {
        super(msg);
        this.value = value;
    }
    public int getValue() {
        return value;
    }
}
class Demo5 {
    int div(int a, int b) throws FuShuException {
        if(b<0)
             throw new FuShuException("出现了除数是负数的情况------- /by fushu", b); //手动通过throw关键字跑出一个自定义异常对象
        if(b == 0) 
            throw new ArithmeticException("被0除了");
        return a/b;
    }
}
public class ExceptionDemo3 {

    public static void main(String[] args) {
        Demo5 d = new Demo5(); 
        try {
            int x = d.div(4, -9);
            System.out.println("x = " + x);
        } catch (FuShuException e){
            System.out.println(e.toString());
            System.out.println("错误的负数是:" + e.getValue());
            return; //
            //System.exit(0); //系统,退出,jvm结束
        } finally{
            System.out.println("finally"); //finally中存放的是一种
        }
        System.out.println("over");
    }

}
package j2se.classdem.test.day9;
/*
 * 内部类的访问规则:
 *  1.内部类可以直接访问外部类中的成员,包括私有
 *    之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用, 格式 外部类名.this
 *  2.外部类要访问内部类,必须建立内部类对象
 *  
 *  访问格式:
 *  1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象
 *  
 *  格式 
 *    外部类名.内部类 变量名 = 外部类对象.内部类对象
 *    Outer.Inner in = new Outer().new Inner();
 *    
 *   2.当内部类在成员位置上,就可以被成员修饰符所修饰
 *   比如   private:将内部类在外部类中进行封装
 *       static:内部类就具备static的特性
 *       当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限
 *       
 *     在外部其他类中,如何直接访问static内部类的非静态成员呢?
 *     new Outer.inner().function()
 *     
 *     在外部其他类中,如何直接访问static内部类的静态成员呢?
 *     Outer.inner().function();
 *  注意:当内部类中定义了静态成员,该内部类必须是static的
 *       当外部类中的静态方法访问内部类时,内部类也必须是static的
 * 
 * 当描述事物时,事物的内部还有事物,该事物用内部类来描述
 * 因为内部事务在使用外部事物的内容
 * 
 * 内部类定义在局部时
 * 1.不可以被成员修饰符修饰
 * 2.可以直接访问外部类中的成员,因为还持有外部类的引用
 *   但是不可以访问他所在的局部中的变量,只能访问被final修饰的局部变量
 *   
 *   匿名内部类:
 *  1.匿名内部类其实就是内部类的简写格式。
 *  2,定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
 *  3,匿名内部类的格式: new 父类或者接口(){定义子类的内容}
 * 4.其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖,可以理解为带内容的对象
 * 5.匿名内部类中定义的方法最好不要超过3个
 class Outer {
    private static int x = 3;
    static class Inner{  //静态内部类
        void function() {
            System.out.println("inner: " + x);
        }
    }
    static class Inner2{
        void show() {
            System.out.println("innner2 show");
        }
    }
/*  public static void method() {
    //  Inner in = new Inner();
    //  in.function();
        new Inner2().show();
    }*/

    void method(final int a)  //内部类定义局部
    {
        final int y = 4;
        class Inner
        {
            void function()
            {
                System.out.println(y);
            }
        }
        new Inner().function();

    }
}
public class InnerClassDemo {

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

    }

}

异常:是什么?是对问题的描述。将问题进行对象的封装。

异常体系:
Throwable
    |--Error
    |--Exception
        |--RuntimeException

异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性。
            也就是说可以被throw和throws关键字所操作。
            只有异常体系具备这个特点。


    --------------
    throw和throws的用法:

    throw定义在函数内,用于抛出异常对象。
    throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。


当函数内有throw抛出异常对象,并未进行try处理。必须要在函数上声明,否则编译失败。
注意,RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。
--------------


如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try。

异常有两种:
    编译时被检测异常
        该异常在编译时,如果没有处理(没有抛也没有try),编译失败。
        该异常被标识,代表这可以被处理。
    运行时异常(编译时不检测)
        在编译时,不需要处理,编译器不检查。
        该异常的发生,建议不处理,让程序停止。需要对代码进行修正。



--------------
异常处理语句:
try
{
    需要被检测的代码;
}
catch ()
{
    处理异常的代码;
}
finally
{
    一定会执行的代码;
}

有三个结合格式:
1.  try
    {

    }
    catch ()
    {
    }

2.  try
    {

    }
    finally
    {

    }


3.  try
    {

    }
    catch ()
    {
    }
    finally
    {

    }

//记住一点:catch是用于处理异常。如果没有catch就代表异常没有被处理过,如果该异常是检测时异常。那么必须声明。

注意:
1,finally中定义的通常是 关闭资源代码。因为资源必须释放。
2,final


package pack;

/*
为了简化类名的书写,使用一个关键字,import.
import 导入的是包中的类。
建议,不要写通配符 * ,需要用到包中的哪个类,就导入哪个类。



c:\myclass

c:\myclass\packb\DemoA.class
c:\myclass\packb\haha\DemoZ.class

import packb.*;
import packb.haha.*;


建立定包名不要重复,可以使用url来完成定义,url是唯一的。

www.itcast.cn

package cn.itcast.demo
package cn.itcast.test


*/

import packb.haha.hehe.heihei.*;
import packa.*;
import packb.*;


class  PackageDemo
{
public static void main(String[] args) 
{

    DemoC c = new DemoC();

//      packa.DemoA d = new packa.DemoA();
//      d.show();

//      packb.DemoB d = new packb.DemoB();
//      d.method();
}
}



/*

PackageDemo.java:8: 找不到符号
符号: 类 DemoA
位置: 类 pack.PackageDemo
               DemoA d = new DemoA();
               ^
PackageDemo.java:8: 找不到符号
符号: 类 DemoA
位置: 类 pack.PackageDemo
               DemoA d = new DemoA();
                             ^
2 错误

错误原因:类名写错。

因为类名的全名是:包名.类名




PackageDemo.java:8: 软件包 packa 不存在
               packa.DemoA d = new packa.DemoA();
                    ^
PackageDemo.java:8: 软件包 packa 不存在
               packa.DemoA d = new packa.DemoA();
                                        ^
2 错误


错误原因:packa包不在当前目录下
需要设置classpath,告诉jvm去哪里找指定的packa包。



PackageDemo.java:8: packa.DemoA 在 packa 中不是公共的;无法从外部软件包中对其进
行访问
               packa.DemoA d = new packa.DemoA();
                    ^
PackageDemo.java:8: packa.DemoA 在 packa 中不是公共的;无法从外部软件包中对其进
行访问
               packa.DemoA d = new packa.DemoA();
                                        ^
2 错误

错误原因:有了包,范围变大,一个包中的类要被访问,必须要有足够大的权限。
所以被访问的类要被public修饰。



PackageDemo.java:9: show() 在 packa.DemoA 中不是公共的;无法从外部软件包中对其进
行访问
               d.show();
                ^
1 错误

错误原因:类公有后,被访问的成员也要公有才可以被访问。


        总结:
        包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。

        不同包中的子类还可以直接访问父类中被protected权限修饰的成员。

    包与包之间可以使用的权限只有两种,public  protected。


                 public   protected       default     private
    同一个类中     ok         ok             ok          ok
    同一个包中     ok         ok             ok
    子类           ok         ok             
    不同包中       ok



    java.lang : java的核心包 jdk1.2版本以后,该包中的类自动导入。
    java.awt: 用于制作图形界面。
    java.io:input output  用于操作设备上的数据。
    java.util : 这里定义是java的工具类。集合,日期。
    java.net:用于网络通讯的。
    java.applet:  application  let        server  let    servlet      java server page   jsp  

    class haha implements Servlet

    class hehe extends HttpServlet

    */
 类似资料: