内部类
1、概念
在一个类的内部定义一个类,这个类就叫内部类
一般来说内部类继承自某个类或实现某个接口,内部类的代码可以创建其外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口,同时无论外部类是否继承一个类或者实现一个接口都对内部类没有影响。
2、作用
- 内部类可以很好的隐藏实现,一般的非内部类不允许又private和protected,但内部类可以
- 内部类可以实现多重继承
- 内部类拥有外部类的所有访问权限
- 可以避免父类和接口同方法时的覆盖问题
3、对于内部类作用的体现
1. 内部内可以很好的隐藏实现
由于外部类不允许定义为private或者protected,如果我们要隐藏一些我们实现细节,就可以通过内部类来实现,比如支付时比较核心的功能,需要我们尽可能的隐藏其实现细节,调用者只需要能能够使用即可,外部的调用无法看到实现类的名字,只需要通过调用外部类的方法创建内部类的对象,这个外部类的方法能返回内部类的一个实例对象,完成对内部类的调用,同时可以通过这个实例对象,调用内部类的方法。
public class test1119 {
public static void main(String[] args) throws Exception {
testA testA = new testA();
testB getinner = testA.getinner();
getinner.pay();
}
}
class testA{
public inner getinner(){
return new inner();
}
private class inner implements testB{
public void pay(){
System.out.println("内部类测试");
}
}
}
interface testB{
void pay();
}
2. 内部类可以实现多重继承
显示生活中存在多重继承关系的,比如孩子同时继承父母的基因,在java中,一个类只支持单继承,多实现,但是对于这种情况用接口直接定义父类(父母)不太合理,这里就发挥了内部类的作用。
public class test1119 {
public static void main(String[] args) throws Exception {
test1119 test1119 = new test1119();
test1119.work();
test1119.dancing();
}
public void work(){
new child1().work();
}
public void dancing(){
new child2().dancing();
}
private class child1 extends father{
@Override
public void work() {
System.out.println("子类学会了工作");
}
}
private class child2 extends mothor{
@Override
public void dancing() {
//super.dancing();这里会出现父类的方法
System.out.println("子类学会了跳舞");
}
}
}
class father{
public void work(){
System.out.println("父亲负责工作");
}
}
class mothor{
public void dancing(){
System.out.println("母亲会跳舞");
}
}
3. 内部类拥有外部类的所有访问权限
由于非静态类会持有外部类的引用,因此,非静态内部类可以访问外部类的所有属性及方法,这样可以为程序的设计带来极大的灵活性
public class test1119 {
public static void main(String[] args) {
out out = new out();
father instance = out.instance();
instance.work();
}
}
interface father{
void work();
}
class out{
private String name1="外部类";
public inner instance(){
return new inner();
}
private class inner implements father{
@Override
public void work() {
name1="内部类修改父类的";
System.out.println("内部类实现");
System.out.println(name1);
}
}
}
4、可以避免父类和接口同方法名时的覆盖问题
当一个类要继承一个类,还要实现一个类,这个时候你发现继承的类和实现的接口里面出现了同名的方法,但是却修改继承类和接口的方法名,这时候就需要内部类
public class test1119 extends father111 implements father222{
@Test
public void testA(){
//这里的work时继承父类的同名方法而不是接口的,产生了覆盖
//这时候就需要采用内部类来解决
this.work();
children111 out1 = new children111();
out1.work();//这是用于继承的父类
father222 instance = out1.instance();
instance.work();//实现了father222接口
}
}
class children111 extends father111{
public inner instance(){
return new inner();
}
private class inner implements father222{
@Override
public void work() {
System.out.println("实现了father222接口");
}
}
}
//用于继承的父类
class father111{
public void work(){
System.out.println("这是用于继承的父类");
}
}
//用于实现的接口
interface father222{
void work();
}
调用内部类的时候需要注意的时候
4 内部类的类别
- 成员内部类
作为一个外部类的成员存在,与外部类的成员变量和方法并列 - 局部内部类
在方法中定义的内部类称为局部内部类。与局部变量类似,局部类部类不能有访问说明符,因为它不是类的一部分,但是它可以访问当前代码块内的常量和外部类的所有变量 - 静态内部类
如果你不需要内部类对象与其外部类对象之间有联系,那你可以将内部类声明为static。这通常称为嵌套类(nested class)。想要理解static应用于内部类时的含义,就需要记住,普通类部类对象隐含地保存了一个引用,指向创建它的外部类对象,然而当内部类时static的时候,就不是这样了,嵌套意味者:
——要创建嵌套类的对象,并不需要外围类的对象。
——不能从嵌套类的对象中访问非静态的外围类对象。 - 匿名内部类
匿名内部类属于局部内部类,而且是没有名字的内部类
遵顼局部内部类的规则,同时匿名内部类要求非常小
不能定义静态的方法、类、变量、只能在new的后面
代码块里面时实现的一个接口或者实现的一个抽象类
不要用再去写一个子类去实现接口了,直接简历接口的对象,然后再匿名内部类里面重写方法
public class test1119 {
@Test
public void testA() {
father11 father11 = new father11() {
@Override
public void work() {
System.out.println("父亲能工作养家");
}
@Override
public void eat() {
System.out.println("父亲也需要吃饭");
}
};
father11.eat();
father11.work();
}
}
interface father11{
void work();
void eat();
}
5 注意事项
- 定义个成员内部类,必须使用外部类来创建对象,或者在外部类定义一个方法,方法体创建一个内部类的对象,利用返回值将对象传到调用的地方,不能直接去new
——内部类 对象名 = 外部类的对象.new 内部类();
——外部类对象.含有内部类的对象的方法(); - 外部内不能直接使用内部类成员和方法,可以先创建内部类的对象,然后通过内部类的对象来访问内部类的成员变量和方法
- 内部类时一个编译时的概念,一旦编译成功,就会称为两个完全不同的两个类,一个outer外部类和其定义的inner内部类,编译完成后出现outer.calss和outer$inner.class 两个类