一、内部类
定义:类中还有类,里面的类就叫做内部类,又称之为内置类或嵌套类。
示例:
class Outer//外部类 { class Inter//内部类 { } }
访问规格:
1.内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式: 外部类名.this。
2.外部类要访问内部类,必须建立内部类对象。
访问格式:
1、内部类定义在外部类的成员位置
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象。
格式:
外部类名.内部类名 变量名 =外部类对象.内部类对象;
Outer.Inner in =new Outer().new Inner();
当内部类在外部类中的成员位置上时,可以被成员修饰符所修饰。
如:私有private:将内部类在外部类中进行封装。
静态 static:内部类就具备static的特性。内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
在外部其他类中,直接访问static内部类的非静态成员的格式为:
new外部类名.内部类名().方法名();
new Outer.Inner().function();
在外部其他类中,直接访问static内部类的静态成员格式为:
.内部类名.方法名();
Outer.Inner.function();
注意:
1)当内部类中定义了静态成员时,该内部类必须是static的。
2)当外部类中的静态方法访问内部类时,内部类也必须是static的。
3)内部类通常被定义为private,而很少定义为public。
示例:
/*内部类又称内置类、嵌套类
注:当内部类中定义了静态成员,该内部类必须是静态的
当外部类中的静态方法访问内部类时,内部类也必须是静态的*/
class InnerClass //外部其他类
{
public static void main(String[] args)
{
Outer out=new Outer();
out.method();
//直接建立内部类对象,访问非静态内部类中的成员
Outer.Inner in=new Outer().new Inner();
in.show();
//直接访问静态内部类的非静态成员
//new Outer.Inner().show();
//直接访问静态内部类的静态成员
//new Outer.Inner.show();
}
}
class Outer//外部类
{
int num=3;
//内部类
class Inner//内部类可以直接访问外部类中的成员,包含私有成员。
{ //内部类只有在成员位置上时才可以用修饰符修饰,例如:public,static
int num=4;
void show()
{
int num=6;
System.out.println("inner1:"+num);//当获取num值时是6,
System.out.println("inner2:"+this.num);//当获取this.num值时是4,
System.out.println("inner3:"+Outer.this.num);//当获取Outer.this.num值是3
}
}
void method()//外部类要访问内部类,要建立内部类对象
{
Inner in=new Inner();
in.show();
}
}
<span style="font-size:14px;">
</span>
运行结果为:
2、内部类定义在局部位置
如:在类的方法中定义类。
1)不可以被成员修饰符修饰。如public、private、static等修饰符修饰。它的作用域被限定在了声明这个局部类的代码块中
2)可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。在内部类里面修改方法的局部变量,就会发现编译器报错,所以要使用final修饰局部变量。
示例:
class Outer {//外部类 int num = 3; void method(final int y) { final int x = 9; class Inner//定义在局部位置上的内部类,不可以被修饰符修饰 { void show() { System.out.println("show..." + x + "," + y); } } Inner in = new Inner(); in.show(); } } class InnerClass { public static void main(String[] args) { Outer o= new Outer(); o.method(4); o.method(5); } } <span style="font-size:14px;"> </span>
运行结果为:
二、匿名内部类
1、匿名内部类其实就是内部类的简写格式。
2、定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
3、匿名内部类的格式: new父类或者接口(){定义子类的内容}
4、其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖,可以理解为带内容的对象。
5、匿名内部类中定义的方法最好不要超过3个。
6、使用匿名内部类的好处:简化书写。
7、使用匿名内部类的弊端:不能做强转动作、不能直接调用自己的特有方法。
示例:
abstract class AbsDemo
{
abstract void show();
}
class OutClass
{
private int num=3;
/*class InterClass extends AbsDemo
{
public void show()
{
System.out.println("Hello World!"+num);
}
}
public void method()
{
new InterClass().show();
}*/
//内部类InterClass继承抽象类AbsDemo,并且实现其中的show方法,
//可将上面的注释(/* */)部分改为匿名内部类,如下:
public void method()
{
new AbsDemo()
{
public void show()
{
System.out.println("Hello World!"+num);
}
}.show();
}
}
class NoNameDemo
{
public static void main(String[] args)
{
new OutClass().method();
}
}
运行结果为:
当抽象类中有多个抽象方法时,继承它的类要实现其中的抽象方法。
示例:
abstract class AbsDemo
{
abstract void show();
abstract void show2();
}
class OutClass
{
private int num=3;
/*class InterClass extends AbsDemo
{
public void show()
{
System.out.println("show:"+num);
}
public void show2()
{
System.out.println("show2:"+num);
}
}
public void method()
{
InterClass in=new InterClass()
in.show();
in.show2();
}*/
//内部类InterClass继承抽象类AbsDemo,并且实现其中的方法,
//可将上面的注释(/* */)部分改为匿名内部类,如下:
//注:匿名内部类中定义的方法最好不要超过3个
public void method()
{
AbsDemo a=new AbsDemo()
{
public void show()
{
System.out.println("show:"+num);
}
public void show2()
{
System.out.println("show2:"+num);
}
};
a.show();
a.show2();
}
}
class NoNameDemo
{
public static void main(String[] args)
{
new OutClass().method();
}
}
运行结果为:
三、异常
异常:就是程序中在运行时出现不正常情况。
由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:
a).严重的问题:对于严重的问题,Java通过Error类进行描述,一般不编译针对性的代码对其进行处理。
对于非常严重的问题,Java通过Exception类进行描述。
注:无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。
向上抽取完后就构成了Java的异常体系Throwable。Exception和Error的子类名都是以父类名作为后缀。
异常的处理:
try{ 需要被检测的代码 }
catch( 异常类 变量 ){ 处理异常的代码/处理方式 }
finally{ 一定会执行的代码 } //通常用于关闭资源,因为资源必须要释放。finally只有一种情况不会执行:System.exit(0)时。
对多异常的处理:
1.声明异常时,建议声明更为具体的异常,这样处理的更为具体。
2.对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现了继承关系,父类异常catch块放在最下面。
3.建议在进行catch处理时,catch中一定要定义具体处理方式,不要简单的就写一条输出语句。
对捕获到的异常对象进行常见方法操作:
获取异常信息,返回字符串。
获取异常类名和异常信息,返回字符串
获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void。
通常用该方法将异常内容保存在日志文件中,以便查阅。
好处:
a).将问题进行封装。
b).将正常流程代码和问题处理代码相分离,方便阅读。
自定义异常:由于项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对这些特有的问题可以按照java中的面向对象思想。将特有的问题,进行自定义的异常封装。定义类继承Exception或者RuntimeException
作用:a).让该自定义异常具备可抛性。
b).让该类具备操作异常的共性方法。
示例:除数不能为负数。如为负数,抛出异常。
class FuShuException extends Exception//自定义异常
{
FuShuException(String message)
{
super(message);
}
}
class Test
{
public int div(int a,int b)throws FuShuException//抛出异常
{
if(b<0)
throw new FuShuException("除数不能为负数。");//抛出异常
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
try
{
System.out.println(new Test().div(4,-1));
}
catch (FuShuException fushu)//捕获异常
{
System.out.println(fushu.toString());
}
}
}
<span style="font-size:14px;">
</span>
运行结果为:
注:1.当函数内部出现了throw抛出异常对象时,那么就必须要给出对应的处理动作。要么在内部处理异常(try,catch),要么在函数上声明(throws),让调用者进行处理。一般情况,函数内出现异常,函数上需要声明。
2.自定义异常必须是自定义类继承Exception,因为异常体系有一个特点:异常类和异常对象都具有可抛性。这个可抛性是Throwable这个体系中的独有特性,只有这个体系中的类和对象才可以被throw和throws操作。
throw和throws的区别:
后面跟异常类名。并且可以跟多个,用逗号分隔。
后面跟异常对象。当函数内容有throw抛出异常对象,并且未进行try处理时,必须要在函数上声明,否则编译失败,RuntimeException及其子类除外,可不用进行声明。
RuntimeException运行时异常:是Exception中特殊的子类异常。
如果在函数内抛出该异常,函数上可以不用进行声明,编译一样通过。
如果在函数上声明该异常,调用者可以不用进行处理,编译一样通过。之所以不用在函数上进行声明,是因为不需要让调用处理。
异常的分类:
1.编译时被检测的异常:该异常在编译时,如没有处理(throw或try),编译失败;该异常被标识,代表可以被处理。
2.编译时不被检测的异常:即运行时异常RuntimeException及其子类,在编译时,不需要处理,编译器不检查,该异常的发生,不建议处理,让程序停止,需要对代码进行修正。
异常格式:
1.try{ } catch( ){ }
2.try{ } catch( ){ } finally{ }
3.try{ } finally{ }
注:catch用于处理异常,如果没有catch就代表异常没有被处理过。如果异常是检测时异常,那么必须进行声明。
异常的注意事项:
1.在子父类覆盖时,子类抛出的异常必须是父类的异常或该异常的子类。
2.如果父类抛出多个异常,那么子类只能抛出父类异常的子集。
3.在子父类覆盖时,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。
四、包Package
作用:
1.对类文件进行分类管理。
2.给类提供多层命名空间。
3.写在程序文件的第一行。
4.类名的全称的是:包名.类名。
5.包也是一种封装形式。
规则 :
1.包必须写在程序的第一行。因为要先有包,才知道类文件的存放地方。
2.类的全称:包名.类名。
3.编译定义了包的程序文件时,在编译时要指定包的存储目录。
示例:创建一个包
package pack;//包名:命名规则:所有字母全部小写
class PackDemo
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
运行结果为:
注:如果在dos命令行中运行这个类,但是当前路径下没有这个类,可以切换到该类所存在的目录下,通过set classpath=该类所在的目录,然后再执行该类。
包与包之间的访问:
1.被访问的包中的类以及类中的成员需要public修饰。
2.不同包中的子类可以直接访问父类中被public或protected权限修饰的成员。
3.包与包之间可以使用的权限只有两种:public或protected。
注:一个.java文件里面,不能出现两个以上的公有类或者接口。因为被public修饰的类名必须与java文件名相同。
导入包:import
作用:简化类名的书写。一个程序只有一个包,但可以有多个import。用来导入包中的类,不导入包中的包。
如:import pack.*; //impart导入的是pack包中所有的类。
建议:
在导入包时,如果包中有很多类,可以使用通配符*来替代包中的所有类。但是,建议不要使用通配符 *,因为将不需要使用的类导入后,会占用内存空间。所有在编写程序时,要使用包中的哪些类,就导入哪些类。
创建包名不要重复,可以使用url来完成定义,因为url是唯一的。如:package cn.itheima.Demo。
导入的不同包中有相同类时,必须写类的全名以区分,否则将会报错。
jar包:
当类越来越多,我们可以用包来装;当包越来越多时,我们可以将包进行压缩。而java中用jar这个工具来对包进行压缩。压缩后的后缀名为jar。
jar.exe工具的一些命令:
创建jar包
jar -cvf mypack.jar packa packb
查看jar包
jar -tvf mypack.jar [>定向文件]
解压缩
jar -xvf mypack.jar
自定义jar包的清单文件
jar -cvfm mypack.jar mf.txt packa packb
jar包的好处:
1、可以将多个包进行压缩到为一个文件。方便项目的携带。
2、 方便于使用,只要在classpath设置jar路径,即可以执行jar包中的java程序。
3、 数据库驱动,SSH框架等都是以jar包体现的。
示例:创建包packa
package packa;//创建包packa
public class PackDemo1
{
public static void method()
{
System.out.println("method");
System.out.println("Hello World!");
}
}
创建包packb,并且导入packa包
package packb;//包名:命名规则:所有字母全部小写
import packa.PackDemo1;//导入packa包中的PackDemo1类
class PackDemo2
{
public static void main(String[] args)
{
new PackDemo1().method();
}
}
运行结果为:
然后在本地路径下生成packa,packb包:
创建jar包:
创建成功后,在本地目录下生成mypack.jar包:
查看mypack.jar包:
解压mypack.jar包: