11.final关键字、内部类

final关键字

final表示最终的,在Java中可以用来修饰 类、变量、方法

1.final修饰的类,不能被继承

2.final修饰的变量,不能被重新赋值,修饰后的变量就是常量

3.final修饰的方法,不能被重写

内部类(了解)

把类定义在其他类的内部,这个类就称为内部类

内部类的访问特点:

1.内部类可以直接访问外部类的成员,包括私有的

2.外部类访问内部类的成员,必须要创建对象

package com.iweb.day8.inner1;

public class Outer { //外部类
    private int num = 100;

    class Inner{  //成员内部类
        int num1 = 200; //内部类的属性
        public void show(){
            System.out.println(num);
            System.out.println(num1);
        }
    }
    //外部类的普通方法中,使用内部类的属性,先创建对象
    public void hello(){
        Inner inner = new Inner();
        System.out.println(num);
        System.out.println(inner.num1);
    }


    //    public void method(){
    //        class Inner{ //局部内部类
    //
    //        }
    //    }
}
package com.iweb.day8.inner1;

import java.util.ArrayList;
import java.util.HashMap;

public class Test {
    public static void main(String[] args) {
        //创建内部类对象,访问内部类中的show方法
        //Inner i =  new Inner();

        //创建普通的成员内部类对象
        //外部类名.内部类名  变量名= 外部类对象.内部类对象
        Outer.Inner inner = new Outer().new Inner();
        inner.show();
    }
}

内部类的分类

成员内部类:在类中的成员位置,定义的类,称为成员内部类。

局部内部类:在局部位置定义的类,称为局部内部类。

成员内部类的修饰符:

private:为了保证数据的安全性

private修饰的内部类,不能被外部调用

static:为了方便访问数据

static修饰的内部类,只能访问外部被static修饰的成员

package com.day11.inner1;

public class Outer { //外部类
    private int num = 100;
    private static int num2 = 200;

    static class Inner{  //成员内部类
        int num1 = 200; //内部类的属性
        public void show(){
            //不能调用外部类非静态成员
            //            System.out.println(num); 
            System.out.println(num1);
            System.out.println(num2);
            hello();
        }
        public static void show1(){
            System.out.println(num2);
            hello();
        }
    }
    //外部类的普通方法中,使用内部类的属性,先创建对象
    public static void hello(){
        Inner inner = new Inner();
        System.out.println(inner.num1);
    }

}
package com.day11.inner1;

import java.util.ArrayList;
import java.util.HashMap;

public class Test {
    public static void main(String[] args) {


        //静态内部类中的方法访问
        //创建静态内部类对象调用,调用普通方法
        Outer.Inner inner = new Outer.Inner();
        inner.show();
        //可以通过外部类名.内部类名.方法名调用静态方法
        Outer.Inner.show1();
    }
}

局部内部类的成员访问特点:

1.局部内部类访问外部类的成员,可以正常访问

2.局部内部类访问局部变量,这个局部变量必须是常量,用final修饰 。

为什么局部内部类访问的局部变量必须是常量?

局部变量随着方法加载而调用,随着方法调用完毕而消失,而内部类的对象,是在堆中,堆中的对象将来有垃圾回收器回收,所以,即使对象不用了,也不会马上消失。

加上final 修饰常量,常量的值会一直保存,对象可以继续使用这个值。

jdk1.8中,对于局部内部类访问的局部变量做了优化,,如果被局部内部类访问了,默认认为你是一个final修饰的常量。

package com.day11.inner2;
/*
局部内部类,定义在某个类的方法中的
 */
public class Outer {
    private String name = "jack";
    private static int num = 100;

    public void method(){
        System.out.println("这个外部类的method方法");
        String s = "hello";
//        s = "world";
        class Inner{
            public void show(){
                hello(); //可以直接访问外部类的成员方法
//                s = "world";
                //可以直接访问外部类的成员属性
                System.out.println(name);
                System.out.println(num);
                //访问局部变量,局部变量必须是常量
                System.out.println(s);
                System.out.println("这个是局部内部类的方法");
            }
        }
        //方法内部创建内部类对象,并访问内部类的方法
        Inner inner = new Inner();
        inner.show();
    }

    public void hello(){
        System.out.println("hello~");
    }
}
package com.day11.inner2;

public class Test2 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();
    }
}

匿名内部类

其实是内部类的一个简写的写法

前提:必须要存在一个类或者一个接口,在其它类中继承或者实现,

写法:

class Outer{

new 类或者接口名(){

重写方法

}

}

本质上,匿名内部类,其实是继承了某个类的子类或者是接口的实现类对象。

package com.day11.inner3;
/*
提供给匿名内部类的接口
 */
public interface Inter {
    void show1();
    void show2();

}
package com.day11.inner3;

public class Outer {
    //如果没用匿名内部类去实现接口的步骤是:
    //1.创建类,实现接口
    //2.实现类重写方法
    //3.创建实现类对象,调用方法

    //匿名内部类
    //把创建接口的实现类、创建对象的步骤都集合在一起了
    public void method(){
  /*      new Inter(){  //new了一个接口的实现类对象
            @Override
            public void show1() {
                System.out.println("匿名内部类重写接口的show1方法");
            }

            @Override
            public void show2() {
                System.out.println("匿名内部类重写接口的show2方法");
            }
        }.show1();

        new Inter(){  //new了一个接口的实现类对象
            @Override
            public void show1() {
                System.out.println("匿名内部类重写接口的show1方法");
            }

            @Override
            public void show2() {
                System.out.println("匿名内部类重写接口的show2方法");
            }
        }.show1();

   */
        //使用多态的写法改进局部内部类
        Inter inter = new Inter() {
            @Override
            public void show1() {
                System.out.println("这是匿名内部类重写接口的show1方法");
            }

            @Override
            public void show2() {
                System.out.println("这是匿名内部类重写接口的show2方法");
            }
        };
        inter.show1();
        inter.show2();


    }
}
package com.day11.inner3;

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();
    }
}

练习

package com.day11.inner4;

public interface Inter {
    void show();
}
package com.day11.inner4;

public class Outer {
    public static Inter method(){
        Inter inter = new Inter() {
            @Override
            public void show() {
                System.out.println("HelloWorld");
            }
        };
        return inter;
    }
}
package com.day11.inner4;

public class Test {
    public static void main(String[] args) {
        Outer.method().show();
        //Outer类中存在静态方法method()
        //show方法来自于接口Inter,将来在method方法中,
        //以局部内部类的方式出现
        //Outer.method()后面继续调用show方法,
        //那么说明method()方法必定返回一个Inter的实现类对象
        //执行这个内容,在后台输出一个"HelloWorld"
    }
}

类执行顺序

1、

public class Father {

    private static String static_field = getStaticField();

    private String field = getField();

    public int j = 18;

    private static String getStaticField() {
        System.out.println("父类静态属性");
        return "father";
    }

    private String getField() {
        System.out.println("父类属性");
        return "father";
    }

    public Father() {
        System.out.println("父类构造方法");
    }

    static {
        System.out.println("父类静态代码块");
    }

    {
        System.out.println("父类代码块");
    }
}
public class Son extends Father {
    private static String son_static_field = getSonStaticField();

    private String son_field = getSonField();

    public int i=getI();//属性加载是有顺序的,自上而下加载

    public int j = 18;

    public final static int z = 18;


    private int getI(){
        return j;
    }

    public static String getSonStaticField(){
        System.out.println("子类静态属性");
        return "son";
    }

    public String getSonField(){
        System.out.println("子类属性");
        return "son";
    }


    public Son() {
        System.out.println("子类构造方法");
    }

    static {
        System.out.println("子类静态代码块");
    }

    {
        System.out.println("子类代码块");
    }

    /**
 * 主类所在类初始化,初始化静态方法
 * @param args
 */
    public static void main(String[] args) {

    }
}

public class InitTest {
    public static void main(String[] args) {
        //        Father father = new Father();
        //        System.out.println("i: " + father.j);
        //        Son son = new Son();
        //        System.out.println("i: " + son.i);


        //      Son.getSonStaticField();


        Son[] sons = new Son[12];

    }
}

2、

package com.day11.order;

public class Base {
    String name = "base";

    public Base() {
        sayHello();
    }

    public void sayHello() {
        System.out.println(name);
    }
}
package com.day11.order;

public class Sub extends Base{
    String name="sub";

    @Override
    public void s
    ayHello(){
        System.out.println(name);
    }

    public static void main(String[] args) {
        new Sub();//null
    }
}
  • 16
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值