内部类

Posted chhyan-dream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内部类相关的知识,希望对你有一定的参考价值。

一、内部类的概念

     定义在类中或接口中的类称之为内部类。

     如果某个类只在另一个类中或另一个类的某个方法中使用,而不希望在整个项目中单独定义这个类,则可以通过定义内部类的方式,将这个类定义在需要使用它的类的内部或者该类方法的内部。

二、内部类的分类

 内部类分为方法内部类、成员内部类、静态内部类和匿名内部类。

1.方法内部类

  方法内部类的定义:在一个方法的内部定义的类,称之为方法内部类。方法内部类只能在当前定义到方法的结尾之间内能够被使用。

  如果某个类只在某个方法内部使用到,则可以将该类声明在方法内,限定其使用的范围。

 方法内部类的特点;

  1.  可以具有成员变量和成员属性
  2. 不能有静态变量和静态方法。因为此时内部类的寄生环境——外部类的方法还未生成,静态变量和静态方法不能访问
  3. 可以声明静态常量。常量放置在常量区。
  4. 可以继承其他类或者实现接口。
  5. 可以使用外部类的成员属性和成员方法。
  6. Jdk8之前不能访问包裹当前内部类的方法中定义的局部属性,除非将其声明为final;Jdk8之后可以访问了,但不能对该值进行修改,如果进行修改,访问会报错。即:内部类可以访问外部类的变量,外部类的变量不可以修改(通常修饰为final)。

         

class Person {
    private String name;
    public void say() {
        System.out.println("说...");
    }
    
    
    //方法内部类
    public void eat() {
        String food = "羊肉串";
        //方法内部类
        class Cooker {
            //1.可以具有成员变量和成员方法
            private String tool = "菜刀";
            //2.可以有静态常量,不能有静态变量和方法
            private static final String name = "张三";
            public void cook() {
                System.out.println("厨师使用"+ tool + "做菜给"  + name +"" + food);
                //5.可以调用外部方法
                say();
            }            
        }
        //6. 内部类访问方法内的成员变量,该变量不能修改
        //food = "牛肉串";
        
        Cooker cooker= new Cooker();
        cooker.cook();
        
        System.out.println("吃...");
        
        
        //4.可以继承和实现接口
        class SichuanCooker extends Cooker {}                
    }
}

2.成员内部类

   定义在一个类内部,可以当做类的一个成员使用的内部类称之为成员内部类。

   用法:如果某个类内部还需要具有一个类结构,且需要外部类作为环境存在,则可以定义成员内部类。

  成员内部类的特征:

  1. 成员内部类可以定义成员属性和成员方法。
  2. 成员内部类不可以定义静态变量和静态方法。
  3. 成员内部类可以定义静态常量。
  4. 成员内部类可以访问外部定义的成员属性,成员方法和静态方法。
  5. 可以通过访问权限修饰符修饰成员内部类。
  6. 可以在外部类中使用成员内部类。
  7. 在访问权限允许的情况下,可以在外部类之外通过对象来使用成员内部类。
  8. 可以继承类和实现接口。
class Outer {
    String Oname;
    public void eat(){};
    //6.外部方法可以访问内部类
    public void run(Inner inner){};
    class Inner {
//3.成员内部类可以定义静态常量
private static final String name ="张安";
//1.成员内部类可以定义成员属性和成员方法
public void say() {
            System.out.println("说..." + Oname);
            //4.内部类可以访问外部类的方法
            eat();
        }
    }
    
    //8.一个内部类可以继承另外一个内部类
    public class Inner2 extends Inner{};
}
public class Demo02 {
    public static void main(String[] args) {
        Outer ou01 = new Outer();
        //7.可以使用外部类对象.new Inner()方式创建内部类对象
        Inner in01 = ou01.new Inner();
        in01.say();
    }

}

3.静态内部类

  用static修饰的成员内部类就是静态内部类;其本质上是成员内部类的静态版本。

  静态内部类的特点:

  1. 可以定义成员属性和成员方法。
  2. 可以定义静态属性和静态方法。
  3. 静态内部类不可以访问外部类中非静态的成员属性和成员方法。
  4. 在外部类的内部,可以使用静态内部类。
  5. 可以通过访问权限修饰符修饰内部类。
  6. 在访问权限允许的情况下也可以在外部类之外通过【外部类.内部类】的方式访问静态内部类。
  7. 可以继承类和实现接口。
class Outer {
//4.在外部类可以使用静态内部类
private Inner in3 = null; static class Inner {
//2.可以定义静态成员和方法
private static String name;
//1.可以定义成员属性和方法
private int age; public static void say(){ System.out.println("说..."); } public static void say2() { System.out.println("说2..."); } } } public class StaticInnerClass { public static void main(String[] args) {
//7.可以通过外部类.内部类方法访问静态内部类 Outer.Inner inner
= new Outer.Inner(); } }

4.匿名内部类

     定义: 当new一个类(或接口)之后,在其后紧跟一个大括号,此时new的不是这个类或接口;而是创建了这个类或接口的匿名的子类(或者匿名实现类),其中大括号内为子类(或匿名实现类)的实现代码,new出来的是这个匿名内部类的对象。

    用法:抽象类、普通类、接口都可以使用匿名内部类的用法;

    匿名内部类的好处:内名内部类用起来减少了类的声明,简单方便,使用场景较多。

    

**
 * 匿名内部类
 * @author Administrator
 *
 */
abstract class Car {
    public abstract void run();
}

//抽象类的实现类
class Automobile extends Car {

    @Override
    public void run() {
        System.out.println("以60km/h速度跑...");
    }    
}
class TransDemo {
    public void trans(Car car) {
        System.out.println("准备货物...");
        System.out.println("发送货物...");
        //传输方法
        car.run();
        System.out.println("接收货物...");
        System.out.println("卸载货物...");
    }
}

interface Info01{
    public void mx();
}

public class Demo04 {
    public static void main(String[] args) {
        //1.--普通类
        TransDemo tDemo = new TransDemo();
        //传入子类
        tDemo.trans(new Automobile());
        
        //2.方法内部类
        class Train extends Car {

            @Override
            public void run() {
                System.out.println("火车以160km/h速度跑...");
            }    
        }        
        TransDemo tDemo1 = new TransDemo();
        tDemo1.trans(new Train());
        
        
        //3.匿名内部类
        //--new 一个Car的子类的匿名内部类,该处相当于省去了class XXX extends
        //接口与之类似
        TransDemo tDemo2 = new TransDemo();
        tDemo2.trans(new Car() {

            @Override
            public void run() {
                System.out.println("飞车以1600km/h速度飞...");                
            }            
        });
        tDemo2.trans(new Automobile() {
            @Override
            public void run() {
                super.run();                
            }        
        });
        
        //4.实例化一个借口的匿名内部类
        new Info01() {
            @Override
            public void mx() {                
                System.out.println("mx...");    
            }            
        };
    }

}

 

 

  

  

以上是关于内部类的主要内容,如果未能解决你的问题,请参考以下文章

片段 - 全局视图变量与本地和内部类侦听器和内存泄漏

为啥片段类应该是公开的?

ForegroundService没有从片段开始?

在内部片段类中使用ListView

自定义无内存泄漏的Handler内部类

底部导航 如何从片段内部更改片段