一、内部类概述
1内部类概述
1 内部类对象可以访问其所在的外部类的所有属性,包括私有属性。因为内部类被当做外部类的成员,同一个类的成员可以相互访问。但是外部类并不能访问内部类中的实现细节。
2内部类提供了更好的封装,可以隐藏在外部类之中,不被同一个包中的其他类所见。
3匿名内部类还可以方便地定义运行时回调和用于仅需要一次使用的类。
4使用内部类编写事件驱动程序时很方便。
2实例内部类和静态内部类的区别
1静态内部类和实例内部类最大的区别是,实例内部类的对象实例,必须在有定义他的外部类的对象实例存在的情况下才能创建。其对象实例保存有指向他的直接外部类对象实例的引用,静态内部类的对象实例创建则不受此限制。
2实例内部类不能定义静态成员,而静态内部类可以定义任意形式的成员。
3.内部类的应用场景
在描述A事物的时候,发现描述的A事物内部还存在另外一个比较复杂的事物B时候,而且这个比较复杂事物B还需要访问A事物的属性等数据,那么这时候我们就可以使用内部类描述B事物。 简单的说,如果一个类需要访问另外一个类的很多属性的时候,这时可以使用内部类。
3.1例如:
人————心脏
Class 人{
血
氧气
等。。。。。。
Class 心脏{
}
}
内部类的好处:内部类可以访问外部类的所有成员。
4内部类需要注意的细节
1.如果外部类与内部类存在同名的成员变量时,在内部了中默认情况下是访问内部类的成员变量。
2.如果外部类与内部类存在同名的成员变量时,可以通过“外部类.this.成员变量名”指定访问外部类的成员。
3.私有的成员内部类只能在外部类提供一个方法创建内部类的对象进行访问,不能再其他类创建对象了。
4.成员内部类一旦出现了静态的成员,那么该类也必须使用static修饰。
原因:静态的成员数据是不需要对象的存在就能访问。
5.在外部类可以直接通过内部类的类名访问内部类的成员如new Inter().getStr();在外部类以外的其他类,则需要通过内部类的完整类名访问内部类。格式如下:
外部类.内部类 内部类对象 = new 外部类().new 内部类()
6.实例内部类是指:声明在外部类的方法体外的,但是没有static关键字修饰的修饰的内部类。注意:在外部类的静态方法或外部类以外的其他类若需要访问内部类,则必须通过外部类创建内部类的实例进行访问。
7.实例内部类可以访问外部类的所有成员;实例内部类只能声明非静态成员。
8.静态内部类既可以声明非静态成员,也可以声明非静态成员;静态内部类遵守类的静态成员所应遵守的一些规则,如不能访问外部类的非静态成员,只能访问外部类的静态成员;静态内部类的对象实例可以独立创建,没有指向外部类的对象实例的引用,也不与任何外部类的对象实例相关联。静态内部类创建对象实例如下:
外部类.静态内部类 静态内部类对象名 = new 外部类.静态内部类();
9静态内部类创建对象实例时,并不需要外部类的实例;静态内部类可以定义非静态成员和静态成员;外部类以外的其他类,需要通过完整的类名访问静态内部类的静态成员,如果要访问静态内部类的实例成员,则需要通过静态内部类的实例;静态内部类可以直接访问外部类的静态成员,如果要访问外部类的非静态成员时,需要通过外部类的实例;
二、局部内部类
1局部内部类是指定义在方法体内的内部类,局部内部类仅在该方法里有效。因此,局部内部类不能被外部类和外部类以外的其他类访问,所以局部内部
2局部内部类可以访问外部类所有成员,包括私有成员,若局部内部类定义在静态方法体内时,局部内部类不能直接访问外部类的非静态成员,但可以访问外部类的静态成员。
3局部内部类不能使用访问修饰符public、private、protected和static关键字修饰,这一点和局部变量是一致的。
4局部内部类只有在其所定义的方法体内有效,不能被外部类和外部类以外的其他类访问。
5局部内部类不能定义static成员。
6局部内部类可以访问外部类的所有成员,包括私有成员。若局部内部类定义在静态的方法体内时,局部内部类不能直接访问外部类的非静态成员,但可以访问外部类的静态成员。若需要调用外部类的非静态成员时,可以通过外部类的实例。
7局部内部类只能访问所在方法的final类型的参数与变量。
三、匿名内部类
1匿名内部类简介
匿名内部类是指在定义时没有名称的内部类,必须在声明时使用new语句类声明。匿名内部类是一种特殊的内部类。
2匿名内部类使用前提
匿名内部类的语法格式:
new <类或接口>([参数列表]){
......
}
匿名内部类必须扩展一个基类或者实现一个接口,但不要显示的使用extends关键字或者implements关键字。如果匿名内部类继承抽象类或实现接口时,还要实现父类及接口所有的抽象方法。
匿名内部类只在其所定义的代码块内使用一次,所以无法为其定义构造方法。匿名内部类总是使用父类的构造方法来创建实例。
3匿名内部类需要注意的事项
1 匿名内部类没有构造方法,但是可以调用父类的构造方法。
2匿名内部类可以访问外部类的所有成员,但匿名内部类定义在方法之中时,只能访问方法中的final类型的参数和局部变量。
3匿名内部类允许非静态代码块对成员进行初始化。
四、异常
1异常:我们的Java程序也是会存在某些不正常的情况的,这些不正常的情况我们就统成为异常。
异常体系:
——————|Throwable 所有异常或者错误的超类
——————————|Error 错误
——————————|Exception 异常
Throwable常用的方法:
toString() 返回当前异常对象的完整类名+病态信息。
getMessage() 返回的是创建Throwable传入的字符串信息。
printStackTrace() 打印异常的栈信息。
——————————|Error 错误:错误一般是由于jvm或者硬件引发的问题,所以我们一般不会通过代码去处理错误的。
——————————|Exception 异常 异常是需要通过代码去处理的。
2如何区分错误和异常呢?
如果程序出现了不正常的信息,如果不正常的信息的类名是以Error结尾的,那么肯定是一个错误。如果是以Exception结尾的,那么肯定就是一个异常。
疑问:下面的异常信息是通过printStackTrace方法打印出来,那么异常对象从何而来呢?
Jvm运行到a/b这个语句的时候,发现b为0,除数为0在我们的现实生活中是属于不正常的情况,jvm一旦发现了这种不正常的情况时候,那么jvm就会马上创建一个对应的异常对象,并且会调用这个异常对象的printStackTrace的方法来处理。
3处理异常——捕获处理
3.1.1异常的处理:
方式一:捕获处理
方式二:抛出处理
3.1.2 捕获处理
Try{
可能发生异常的代码:
} catch(捕获的异常类型 变量名){
处理异常的代码。。。。。。
}
示例:
3.1.3捕获处理要注意的细节:
1.如果try块代码中出了异常经过处理之后,那么try-catch块外面的代码可以正常的执行。
2.如果try块中出现了异常的代码,那么在try块中出现异常代码后面的代码是不会执行的。
3.一个try块后面是可以跟有多个catch块的,也就是一个try块可以捕获多种异常的类型。
4.一个try快可以捕获多种异常的类型,但是捕获的异常类型必须从小到大进行捕获,否则编译报错。
3.1.4问题
1 异常的处理感觉没有多大用,因为都是输出一句话而已?
在开发中,可以将出现问题的代码,跳转到另外的一个页面中,就是重定向。
异常处理非常有用,只不过是由于我们目前接触的知识点太过于局限而已。
2 以后捕获处理的时候,是否就是可以直接捕获超类Exception即可?
不可以这样,因为我们在现实开发中遇到不同的异常类型的时候,往往会有不同的处理方式,所以要分开不同的异常类型处理。
4处理异常——抛出处理
Throw throws
1抛出处理要注意的细节:
1.如果一个方法的内部抛出了一个编译时异常对象,那么必须要在方法上声明抛出。
2如果调用了一个声明抛出编译时异常的方法,那么调用者必须要处理异常。
3如果一个方法内部抛出了一个异常对象,那么throw语句后面的代码都不会在执行了。(如果一个方法遇到了throw关键字,那么该方法也会马上停止执行的)
4 在一种情况下,只能抛出一种异常类型的对象。
-
如上图所示,在if b==0处抛出了一个异常,根据“抛出处理要注意的细节1”,“如果一个方法的内部抛出了一个异常对象,那么必须要在方法上声明抛出。”,也就是说,必须在public static void div(int a,int b)处声明,原因是因为,如果这个方法是你写的,内部你抛出的异常对使用方法的人来说是不可见的,所以你必须要在方法处进行声明,好让用户的使用者进行查看。根据“抛出异常处理要注意的细节2”“2如果调用了一个声明抛出异常的方法,那么调用者必须要处理异常。”,也就是说,在此例中,主函数调用了改异常方法,所以主函数应对该异常进行处理,或者,主函数在向上抛出,丢给jvm去处理。丢给jvm处理如下图:
2抛出处理的形象比喻:
抛出处理就像一个人得了很严重的病,需要从乡里的卫生院转到县里,如果县医院要是治疗不好的话,就要转到市里治疗,层层抛出,层层转院。
3 throw与throws两个关键字对比:
1.throw关键字是用于方法内部的,throws是用于方法声明上的。
2.Throw关键字是用于方法内部抛出一个异常对象的,throws关键字是用于在方法声明上声明抛出异常类型的。
3.Throw关键字后面只能有一个异常对象,throws后面一次可以声明抛出多种类型的异常。
4疑问:抛出处理的作用,何时使用抛出处理,何时使用捕获处理?原则是什么?
如果你需要通知到调用者,你的代码出了问题,那么这时候就使用抛出处理。
如果你的代码是直接与用户打交道,遇到了异常千万不要抛出,在抛的话,就给了用户,这时候就应该使用捕获处理。
5自定义异常类
1自定义异常 步骤
自定义一个类继承Exception即可。
6运行时异常和编译时异常
运行时异常:如果一个方法内部抛出了一个运行时异常,那么方法上可以声明也可以不声明,调用者可以处理也可以不处理;RuntimeException以及RuntimeException子类,都是属于运行时异常。
编译异常(非运行时异常,受检异常):如果一个方法内部抛出了一个编译时异常对象,那么方法上就必须声明,而且调用者也必须要处理;除了运行时异常,都是编译时异常。
1疑问:为什么jvm编译器会如此严格要求编译时异常,对运行时异常如此宽松?
因为运行时异常都是可以通过程序员良好的编程习惯去避免,所以java编译器就没有严格要求处理运行时异常。所以在使用别人写好的方法时,需要看看是否有编译时异常。
五、Finally块
1.Finally 块的使用前提是必须要存在try块才能使用。
示例:
Finally块的代码在任何情况下都会执行的,除了jvm退出的情况。
Finally非常适合做资源释放的工作,这样子可以保证资源文件在任何情况下都会被释放。
2.try块的三种组合方式:
第一种:
比较是用于有异常要处理,但是没有资源要释放的。
try{
可能发生异常的代码;
} catch(捕获的异常类型 变量名){
处理异常的代码
}
第二种:
比较适用于既有异常要处理又要释放资源的代码。
try{
可能发生异常的代码;
} catch(捕获的异常类型 变量名){
处理异常的代码
}finally{
释放资源的代码;
}
第三种:
比较适用于内部抛出的是运行时异常,并且有资源要被释放。
try{
可能发生异常的代码;
}
}finally{
释放资源的代码;
}
六、包
1.问题的提出
假设一个项目组有10个人,每个人分开干,会有类名相同的情况。
包可以解决的问题:
1.解决类名重复产生冲突的问题。
2.便于软件版本的发布。
2.包的作用:
1.java中的包就相当于windows的文件夹。
3.包语句要注意的事项
1.package语句必须位于java文件中的第一个语句。
2.如果一个类加上了包语句,那么该类的完整类名就是包名.类名
4.包名的命名规范
包名全部小写。
5.包语句带来的烦恼
每次编译的时候都需要自己创建一个文件夹,把对应的class文件存储到文件夹中,这个问题比较麻烦。
解决方案:javac -d 指定类文件的存放路径
6导包语句要注意的细节:
1.导包语句格式:
Import 包名.类名;(倒入xxx包中某个类)
2.一个java文件中可以出现多句导包语句。
3.“*”是导包语句的通配符。可以匹配任何的类名。
7导包语句的作用:
简化书写。(误区:把一个类倒入到内存中,并不是这样的,这样做的目的是为了简化书写,在代码中使用到了哪个类,才会将哪个类加载到内存,并不会因为一个导包语句就将所有的类加载到内存。)
8 导包语句的应用场景
什么时候需要使用import语句:
1相互访问的两个类在不同的包下面,需要使用导包语句
2 java.lang 是默认导入的,不需要我们自己导入。
七、Jar包
1.jar包定义
Jar包就是别人已经写好的一些类,然后将这些类进行打包,你可以将这些jar包引入你的项目中,然后就可以直接使用这些jar包中的类和属性以及方法。
Jar是将一系列的文件合并到单个压缩文件里,就像zip那样。然而,同java中其他任何东西一样,jar文件是跨平台的,所以不必关系涉及具体平台的问题。
2如何打jar包
打jar包:需要使用到jdk的开发工具(jar.exe)
Jar的使用格式:
Jar cvf jar 文件的名字 class文件或者是文件夹
3打jar包需要注意的事项:
1一个程序打完了jar之后,必须要在清单文件上指定入口类:格式Main—Class:包名.类名。
2.jar包双击运行仅对于图形化界面程序起作用,对控制台的程序不起作用。
4 jar文件的作用
1.方便用户快速运行一个项目。
2.提供工具类给别人使用。
5 jre = jvm +核心类库(就是java中的jar包)
如果使用jar包里面的类,必须要先设置classpath路径。
八、模板模式
1模板模式:
某类事情的步骤有些是固定的,有些是会发生变化的,那么我们可以为这类事情提供一个模板代码,从而提高效率。
2模板模式的步骤:
1先写出解决该类事情其中的一件的解决方案。
2 分析代码,把会发生变化的代码抽取出来,独立成一个方法。把该方法描述成一个抽象的方法。
3 使用final修饰模板方法,防止别人重写你的模板方法。
九、权限修饰符
1 访问权限修饰符定义:
访问权限修饰符就是控制被修饰的成员的范围可见性。
Public
Protected
Default
Private
注意:在不同包下面只有public 与protected 可以访问,而且protected必须是在继承关系下才能访问。
十、接口下的多态
多态定义:父类的引用类型变量指向了子类的对象或者是接口类型的引用类型变量指向了接口实现类的对象。
接口实现关系下的多态:
接口 变量 = new 接口实现类的对象。
Interface Dao{
Public void add();
Public void delete();
}
//接口的实现类
Class UserDao implements Dao{
Public void add(){
System.out.print(“添加员工成功!!”)
}
Public void delete(){
System.out.print(“删除员工成功”)
}
}
Class Demo 3{
Public static void main(String[] args){
//实现关系下的多态
Dao d = new UserDao(); // 接口的引用类型变量指向了接口实现类的对象。
D.add();
}
}
注意:接口关系下的多态,永远都是调用实现类的方法,因为接口不能存在静态的方法。