一、内部类

定义:类中还有类,里面的类就叫做内部类,又称之为内置类或嵌套类。

示例:

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>

运行结果为:

java内部函数调用外部函数_java内部函数调用外部函数

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>

运行结果为:

java内部函数调用外部函数_内部类_02

二、匿名内部类

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();
	}
}

运行结果为:

java内部函数调用外部函数_外部类_03

当抽象类中有多个抽象方法时,继承它的类要实现其中的抽象方法。

示例:

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内部函数调用外部函数_System_04

 三、异常

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

由来:问题也是现实生活中一个具体的事物,也可以通过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>

运行结果为:

java内部函数调用外部函数_java内部函数调用外部函数_05

注: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!");
	}
}

运行结果为:

 

java内部函数调用外部函数_外部类_06

注:如果在dos命令行中运行这个类,但是当前路径下没有这个类,可以切换到该类所存在的目录下,通过set classpath=该类所在的目录,然后再执行该类。

包与包之间的访问:

        1.被访问的包中的类以及类中的成员需要public修饰。

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

        3.包与包之间可以使用的权限只有两种:public或protected。

java内部函数调用外部函数_System_07

注:一个.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();
	}
}

运行结果为:

java内部函数调用外部函数_外部类_08

然后在本地路径下生成packa,packb包:

java内部函数调用外部函数_外部类_09

创建jar包:

java内部函数调用外部函数_内部类_10

创建成功后,在本地目录下生成mypack.jar包:

java内部函数调用外部函数_内部类_11

查看mypack.jar包:

java内部函数调用外部函数_java内部函数调用外部函数_12

解压mypack.jar包:

java内部函数调用外部函数_System_13