----------------------------------------------------------------------------- android培训、java培训、期待与您交流! --------------------------------------------------------------------------------
什么是内部类?
大部分时候我们将类定义成一个独立的程序单元;在某些情况下,我们把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类(有的也叫嵌套类),包含内部类的类也被称为外部类(有的也叫宿主类)。
内部类主要有如下作用:
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
- 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问;但外部类不能访问内部类的实现细节,例如内部类的属性。
- 匿名内部类适合用于创建那些仅需要一次使用的类。
非静态内部类
定义内部类非常简单,只要把一个类放在另一个类内部定义即可。此处的“类内部”包括类中的任何位置,甚至在方法中也可以定义内部类(方法里定义的内部类被称为局部内部类)。
大部分时候内部类都被作为成员内部类定义,而不是作为局部内部类。成员内部类时一种与属性、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。
成员内部类分为两种:静态内部类和非静态内部类,使用static修饰的成员内部类时静态内部类,没有使用static修饰的成员内部类时非静态内部类。
因为内部类作为其外部类的成员,因此可以使用任意访问控制符如:private、protected和public等修饰。
注意:
外部类的上一级程序单元是包,所以它只有2个作用域:同一个包和任何位置。因此只需两种访问权限:包访问权限和公开访问权限。正好对应省略访问控制符和public访问控制符。省略访问控制符是包访问权限,即同一包中的其他类可访问省略访问控制符的成员。因此,如果一个外部类不适用任何访问控制符修饰,则只能被同一个包中其他类访问。而内部类的上一级程序单元是外部类,它就具有四个作用域:同一个类、同一个包、父子类和任何位置,因此可以使用四种访问控制权限。
内部类的访问规则:
- 内部类可以直接访问外部类中的成员,包括私有;
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式: 外部类名.this
- 外部类要访问内部类,必须建立内部类对象。
访问格式:
- 当内部类定义在外部类的成员位置上,而且非私有,可以在外面其他类中。
可以直接建立内部类对象。
格式:
外部类名.内部类名 变量 = 外部类对象.内部类对象;
Outer.Inner in = newOuter().new Inner();
- 当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行封装。
static:内部类就具备了static的特性。
当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
newOuter.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();
class Outer
{
private int x = 3;
class Inner//内部类
{
//int x = 4;
void function()
{
//int x = 6;
System.out.println("innner :"+Outer.this.x);
}
}
/**/
void method()
{
Inner in = new Inner();
in.function();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method();
//直接访问内部类中的成员。
// Outer.Inner in = new Outer().new Inner();
// in.function();
}
}
注意:
当内部类中定义了静态成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
内部类定义在局部时,
- 不可以被成员修饰符修饰;
- 可以直接放那个吻外部类中的成员,因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
匿名内部类:
- 匿名内部类其实就是内部类的简写格式。
- 定义匿名内部类的前提:
内部类必须继承一个类或者实现接口;
- 匿名内部类的格式: new父类或者接口(){定义子类的内容}
- 其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖,也可以理解为带内容的对象。
- 匿名内部类中定义的方法最好不要超过3个。(最好是两个或是一个)
interface Inter
{
void show(int a, int b);
void func();
}
class Demo
{
public static void main(String[] args)
{
//匿名内部类
Inter in = new Inter()
{
public void show(int a, int b)
{
}
public void func()
{
}
};
in.show(4,5);
in.func();
}
}
异常
就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:两种:一种是严重的问题,一种非严重的问题。
对于严重的,java通过Error类进行描述;
对于Error一般不编写针对性的代码对其进行处理。
对于非严重的,java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。
2.异常的处理
java提供了特有的语句进行处理。
处理异常的基本代码块格式:
try
{
需要被检测的代码;
}
catch (异常类 变量)
{
处理异常的代码:(处理方式)
}
finally
{
一定会执行的语句:
}
3,对捕获到的异常对象进行常见方法操作。
String getMessage():获取异常信息
其实jvm默认的异常处理机制,就是在调用printStackTrace方法。打印异常的堆栈中的跟踪信息。
<<ExceptionDemo.java>>
异常声明throws
在功能上通过throws的关键字声明了该功能有可能会出现问题。
对多异常的处理:
- 声明异常时,建议声明更为具体的异常。这样处理的可以更具体。
- 对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
建立在进行catch处理时,catch中一定要定义具体处理方式。
不要简单定义一句e.printStackTrace(),也不要简单的就书写一条输出语句。
自定义异常
因为项目中会出现特有的问题
而这些问题并未被java所描述并封装对象。
所以对于这些特有的问题可以按照java的对问题封装的思想。
将特有的问题,进行自定义的异常封装。
class Demo
{
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
class ExceptionDemo2
{
public static void main(String[] args) //throws Exception
{
Demo d = new Demo();
try
{
int x = d.div(5,0);
System.out.println("x="+x);
}
catch(Exception e)
{
System.out.println("hahah:"+e.toString());
}
catch (ArithmeticException e)
{
System.out.println(e.toString());
System.out.println("被零除了!!");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
System.out.println("角标越界啦!!");
}
System.out.println("over");
}
}
throw和throws的区别
throws使用在函数上;(写在小括号和大括号之间)
throw使用在函数内;(后面跟的是异常现象)
throws后面跟的是异常类,可以跟多个,用逗号隔开。
throw后面跟的是异常对象。
RuntimeException
Exception中有一个特殊的子类异常RuntimeException;
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
如果再函数上声明了该异常,调用者可以不用进行处理,编译一样通过。
之所以不用在函数声明,是因为不需要让调用者处理;
当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后;
对代码进行修正。
自定义异常时,如果该异常的发生无法再继续进行运算,就让自定义异常继承RuntimeException。
对于异常分两种:
1. 编译时被检测的异常。
2.编译时不被检测的异常(运行时异常,RuntimeException以及其子类)
*/
class FuShuException extends RuntimeException
{
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b)throws Exception//throws ArithmeticException
{
if(b<0)
throw new Exception("出现了除数为负数了");
if(b==0)
throw new ArithmeticException("被零除啦");
return a/b;
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
int x = d.div(4,-9);
System.out.println("x="+x);
System.out.println("over");
}
}
/*
class Person
{
public void checkName(String name)
{
//if(name.equals("lisi"))//NullPointerException
if("lisi".equals(name))//if(name!=null && name.equals("lisi"))
System.out.println("YES");
else
System.out.println("no");
}
}
main()
{
Person p = new Person();
p.checkName(null);
}
*/
记住:
catch是用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常时检测时异常,那么必须声明。
异常在子父类覆盖中的体现;
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者异常的子类。
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。
----------------------------------------------------------------------------- android培训、java培训、期待与您交流!--------------------------------------------------------------------------------
详细请查看:http://edu.youkuaiyun.com/heima/