欢迎来到我的博客

将来的你一定会感激现在拼搏的自己

JavaSE基础day09final、内部类、静态代码块、包、权限修饰符、匿名内部类

 


 

一. 代码块(了解)

(一)概述

1、使用大括号包起来的一段代码。放在不同的位置,有不同的名称,有不同的作用,有不同的执行时机。

2、分类:

       局部代码块

       构造代码块

       静态代码块

       同步代码块(多线程)

 

(二)局部代码块

1、位置:定义在方法中的代码块

2、作用:

       限定变量的生命周期

       在局部代码块中【声明】的变量,只能在局部代码块的范围内使用,一旦出了局部代码块的大括号,变量就不能继续使用了。

       缩短局部变量的生命周期,及时的释放内存空间提升代码的运行效率

3、注意事项:

(1) 代码块可以使用外部的所有资源

(2) 如果是在局部代码块中修改了局部代码块外声明的变量,局部代码块结束之后,并不会消除局部代码块对这个变量的修改。

public class Demo01_局部代码块 {
    public static void main(String[] args) {
        int i = 10;
        // 局部代码块: 作用, 限定 定义在局部代码块中变量作用范围
        // 优势: 不仅仅是范围的限定,也是变量在内存中存储时间的限定,例如y变量,如果局部代码块执行完毕, y就变成了一个无法再使用的变量,很快就会被JVM回收掉
        {
            int y = 20;
            System.out.println(y);
            // 如果是局部代码块之外变量使用,不受局部代码块限制
            i = 88;
        }
        // System.out.println(y);
        System.out.println(i);// 88
    }
}

 

(三)构造代码块

1、位置:定义在类中方法外【成员变量位置】

2、作用:

(1) 创建对象的时候给对象的属性值显性赋值

(2) 提取本类构造方法中的共性内容实现

3、构造代码块的执行说明:

       1、在创建对象的时候执行,由jvm默认调用

       2、在构造方法执行之前,执行

public class Demo02_构造代码块 {
    int i = 10;
    String name;
    // 构造代码块:
    // 运行时机: 当每次创建对象的同时, JVM虚拟机主动调用构造代码块一次, 并且是在构造方法之前
    // 作用: 可以给当前对象中的成员变量进行赋值; 如果当前类型中有多个构造方法, 并且这些构造中有相同的处理逻辑
    // 这些逻辑可以提升到构造代码块中完成
    {
        name = "张三";
        System.out.println("构造代码块运行了");
        System.out.println("我是构造方法");
    }

    public Demo02_构造代码块(){
       // System.out.println("我是构造方法");
    }

    public Demo02_构造代码块(int i){
        this.i = i;
       // System.out.println("我是构造方法");
    }

    public static void main(String[] args) {
        Demo02_构造代码块 demo = new Demo02_构造代码块();
        System.out.println(demo.name);
        Demo02_构造代码块 demo1 = new Demo02_构造代码块(99);
    }
}

 

(四)静态代码块(一定掌握)

1、格式:

       static {

            静态代码块的内容

        }

2、位置:类中方法外

3、作用:

(1) 给类的静态变量赋值

(2) 用来加载只需要加载一次的资源【例如: 加载数据库驱动】

4、执行特点:

(1) 随着类的加载而执行

(2) 静态代码块只执行一次

(3) 执行的时机最早:早于所有的对象相关内容

public class Demo03_静态代码块 {
    int i;
    static int w;
    // 静态代码块:
    // 1. 可以给类型中的静态成员变量进行赋值
    // 2. 静态代码块运行时机: 因为静态都属于类, 因此在当前类进入内存时候(进入方法区),JVM虚拟机主动调用
    // 静态代码块一次
    // 3. 静态代码块使用场景: 如果有代码只需要执行一次, 并且是在所有其他代码运行之前就执行, 那么这些逻辑
    // 可以设计在静态代码块中
    // 举例: 数据库,持久性的存储数据; 需要在交易开始之前, 保证数据库连接成功的(登录数据库,读取数据库登录时用户名和密码)
    // 连接数据库的过程就可以设计在静态代码块中
    static{
       // i = 10;  静态中不能直接使用非静态
       w = 99;
       System.out.println("我是静态代码块");
    }

    public static void main(String[] args) {
        System.out.println(Demo03_静态代码块.w);
        Demo03_静态代码块 dmo = new Demo03_静态代码块();
    }
}

 

二. 内部类(了解)

(一)    概述

1. 定义在一个类中的另一个类就叫做内部类

  举例:在一个类A的内部定义一个类B,类B就被称为内部类

 

2. 格式:

  public class Outer { // 外部类

         public class Inner { }// 内部类

  }

 

  人类: 定义成Person, 人类组成很复杂, 身体器官: 心脏, 肝, 肾...

        心脏: 血压, 心跳, 颜色, 控制身体机能

 

3. 分类: 根据定义的位置不一样以及是否有名分为了不同的内部类,具体分类如下:

  1) 成员内部类

  2) 局部内部类

  3) 匿名内部类(掌握)

 

 

4. 访问特点:

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

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

 

(二)    普通成员内部类

1. 定义位置: 在类中方法外,跟成员变量是一个位置

1. 外界创建成员内部类格式

格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

举例:Outer.Inner oi = new Outer().new Inner();

 

2. 访问方式:

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

(2) 外部类访问内部类的成员,必须先创建内部类对象

public class Body {
    int height = 80;

    public void test(){
        System.out.println("我是test");
    }
    // 普通成员内部类
    class Heart{
        String color = "红色";
        int jump = 100;
        int height = 999;
        public void show(){
            // 1. 内部类中可以直接使用外部类中的成员(成员变量, 方法)
           System.out.println(color + "颜色的心脏,每分钟跳" + jump + "下,血压为:" + height
             + "--" + new Body().height);
            test();
        }
    }

    // 2. 外部类如果想使用内部类成员, 需要创建出一个内部类对象
    public void useHeart(){
        System.out.println(height);
        Heart h = new Heart();
        System.out.println(h.color);
        System.out.println(h.jump);
        h.show();
    }
}

 

public class TestInnerClass {
    public static void main(String[] args) {
        // 1. 测试普通成员内部类使用
        Body b = new Body();
        b.useHeart();

        System.out.println("--------------------------------");
        // 2. 测试普通成员内部类对象在其他类中创建
        // 外部类名.内部类名  对象名 = new 外部类对象().new 内部类对象();
        Body.Heart h = new Body().new Heart();
        // Heart h1 = new Heart();
        System.out.println(h.color);
        System.out.println(h.jump);
        System.out.println(h.height);
        h.show();
    }
}

 

(三)    私有的成员内部类

1、也是一个成员内部类,在成员内部类前面加上一个private关键字

2、访问方式:

  (1) 在外部类以外,不能直接访问外部类中的私有成员内部类

  (2) 可以在外部类中,定义一个访问私有成员内部类的公有方法,让外界可以调用公有方法,间接的访问外部类中的私有成员内部类。

public class Body1 {
    private int height = 80;

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void test(){
        System.out.println("我是test");
    }
    // 普通成员内部类
    private class Heart1{
        String color = "红色";
        int jump = 100;
        int height = 999;
        public void show(){
            // 1. 内部类中可以直接使用外部类中的成员(成员变量, 方法)
            System.out.println(color + "颜色的心脏,每分钟跳" + jump + "下,血压为:" + height
             + "--" + new Body1().height);
            test();
        }
    }

    // 2. 外部类如果想使用内部类成员, 需要创建出一个内部类对象
    public void useHeart1(){
        System.out.println(height);
        Heart1 h = new Heart1();
        System.out.println(h.color);
        System.out.println(h.jump);
        h.show();
    }
}

 

public class TestInnerClass {
    public static void main(String[] args) {
        // 3. 测试私有成员内部类: 通过间接方式访问私有成员内部类
        Body1 b1 = new Body1();
        b1.useHeart1();
    }
}

 

(四)    静态的成员内部类

1、也是一个成员内部类,在成员内部类前面加上一个static关键字

2、访问方式:

(1) 成员内部类是外部类的静态成员,所以可以通过外部类名.内部类名的方式直接访问,而不需要创建外部类的对象

(2) 静态内部类中的非静态成员,需要将所在的内部类对象创建出来之后,才能被调用。

总结:一个类是否需要创建对象,不取决于该类本身是否是静态,而取决于要访问

                 的成员是否是静态

3、静态成员内部类的对象创建格式:    

       外部类名.内部类名 内部类对象名 = new 外部类名.内部类名();

public class Body2 {
    // w表示每天喝多少升水
    static int w = 2;
    // 静态成员内部类
    // 是否需要创建对象调用成员: 如果这个成员是非静态的, 那么创建对象; 如果这个成员是静态成员, 那么不需要创建对象, 类名.直接调用
    static class Shen{
        int day = 1;
        static int wc = 8;
        public void show(){
            System.out.println(day + "天喝了" + w + "升,应该去卫生间"+ wc + "次");
        }
    }
}

 

public class TestInnerClass {
    public static void main(String[] args) {
        // 4. 测试静态成员内部类:
        // 1) 调用静态成员内部类中的静态成员变量
        System.out.println(Body2.Shen.wc);// 8
        // 2) 调用静态成员内部类中非静态成员变量
        // 静态成员内部类对象创建方式:
        // 外部类名.内部类名 对象名 = new 外部类名.内部类名();
        Body2.Shen sh = new Body2.Shen();
        System.out.println(sh.day);// 1
        sh.show();// 1天喝了2升,应该去卫生间8次
    }
}

 

(五)    局部内部类

1. 定义位置: 局部内部类是定义在方法中的类

2. 访问方式:

  (1) 局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用

  (2) 该类可以直接访问外部类的成员,也可以访问方法内的局部变量

public class Demo_局部内部类 {
    public static void main(String[] args) {
        breath();
    }

    public static void breath(){
        // 1. count作为局部变量不能单独获取到, 只能跟着breath方法运行使用
        int count = 10;
        // 2. 局部内部类, 与局部变量类似,只能在方法中定义使用
        class Fei{
            String color = "black";
            public void show(){
                System.out.println("每天吸" + count + "跟烟,总有一天肺就会变成" + color);
            }
        }
        // 3. 局部变量,直接在方法中创建对象使用
        Fei f = new Fei();
        System.out.println(f.color);
        f.show();
    }
}

 

三. final关键字

1、final是一个关键字 含义:最终的,最后的,表示不能再改变的。

2、final关键字:可以修饰类、方法、变量

3、修饰类:

        (1) 表示一个最终类,表示不能有子类,【不能被其他类继承】

        (2) 一旦一个类型不能被继承,那么其中所有的方法都不能被重写

        (3) 不影响当前类的方法被调用

4、修饰方法:

       表示一个最终方法,【该方法不能被重写】

5、修饰变量:

       (1) 表示一个最终变量,该【变量变成了常量】,就只能赋值一次

       (2) 当前项目中,常用的常量一般都定义在一个类的成员位置,甚至专门定义一个常量类,常量命名规范: 所有单词全大写, 多个单词之间使用_进行分隔了,举例: SCHOOL_NAME  PI

       (3) 定义常量的好处:见名知意,容易理解;可维护性高

 

final修饰类代码

// final修饰的类没有子类
public final class FinalClass {
    int i = 10;
    static int w = 20;
    public void fun(){
        System.out.println("我是final类中的fun方法");
    }
}
/*public class FinalClassSub extends FinalClass{ // 报错
}*/

final修饰方法:

public class FinalMethod {
    public final void eat(){
        System.out.println("我是final修饰的吃饭功能, 不能被继承,但是可以直接使用");
    }
}
public class FinalMethodSub extends FinalMethod{
    // 子类继承到了父类中的eat方法,但是因为这个方法是final修饰的,只能使用不能重写
    /*public void eat(){
        System.out.println("我是final修饰的吃饭功能, 不能被继承,但是可以直接使用");
    }*/
}

final修饰变量:

public class FinalVariable {
    // 5. final修饰成员变量: 最好直接赋值(扩展: final修饰成员变量, 必须在创建对象完成之前进行手动赋值)
    final String name = "张三";// 最推荐
    final String sex;

    public FinalVariable(){
        sex = "男";
    }
    int w = 99;
    // 1. final修饰的变量值不能发生改变, final固定的数据第一次手动赋值
    // 2. final修饰的变量称为常量: 所有单词全大写, 多个单词之间_分隔
    public static void main(String[] args) {
        final int I = 10;
        // 3. final修饰基本数据类型,其数值不能发生修改
        // I = 19;
        // 4. final修饰引用数据类型,那么表示这个引用地址值不能发生改变
        final FinalVariable fv = new FinalVariable();
        // fv = new FinalVariable();
        fv.w = 888;
    }
}

 

final代码测试类:

public class TestFinal {
    public static void main(String[] args) {
        // 1. 测试final修饰的类可以正常使用
        FinalClass fc = new FinalClass();
        System.out.println(fc.i);
        System.out.println(FinalClass.w);
        fc.fun();

        // 2. 测试final修饰的方法可以被子类继承, 也可以正常使用
        FinalMethodSub fms = new FinalMethodSub();
        fms.eat();

        FinalMethod fm = new FinalMethod();
        fm.eat();
    }
}

 

四. 包

1. 包的概述: 用来统一分类管理源代码资源的特殊文件夹;这个文件夹会参与编译。

比如:

      com.ujiuye.demo 下的 Person类进行编译的时候类所在的包参与编译,编译后

        字节码文件名:com.ujiuye.demo.Person

        字节码文件中类名:com.ujiuye.demo.Person【全限定类名】  

 

2. 作用:

  (1) 统一管理代码资源

  (2) 保证代码编译后类名唯一

  (3) 保证代码运行的过程直接进入包找到对应的类

 

3. 命名规则:

  (1) 使用公司域名的反写【保证每一个包路径唯一】

  (2) 全部小写

  (3) 包名和包名之间使用.隔开

 

4. 包的声明:

   使用关键字 package + 包路径【IDE生成类的时候自动声明】

 

5. 导包:

  同包下:不需要导包

  不同包:需要导包【jdk的lang包除外】

  使用 import + 包路径

 

6. 注意:

  (1) 没有导包格式之前:使用类的时候不导包的直接使用全限定类名进行使用

                 比如:java.util.Scanner sc = new java.util.Scanner(System.in);

  (2) 使用全限定类名使用类的时候,有点麻烦进行了简化:

                 使用import关键字进行提取导包进行导包

  (3) 作用

    可以把同名字的类使用包做一个详细的划分

import com.ujiuye.homework.Phone;

public class Test {
    // com.ujiuye.innerclass.Test
    // com.ujiuye.block.Test
    Phone p = new Phone();

    // java.lang包下的所有类型可以直接使用, 不需要导包
    String str = "abc";
}

 

五. 权限修饰符

1. 概述: 用来限定资源的使用范围的修饰词汇,就叫做权限(使用)修饰符,不同的符号有不同的限定范围

2. 分类: 从小到大权限罗列

  private :私有的     限定范围:本类中使用

默认的 :啥也不写    限定范围:本类和本包中使用

protected :受保护的  限定范围:本类和本包中使用,不同包下的子类内部可以使用

public :公共的      限定范围:没有范围

 

3. 注意:

1) protected 只修饰方法和变量, 不能修饰类; 保护的是外包子类的内部

2) 总结: 修饰成员变量,为了满足封装特点,使用private修饰;

         修饰类,和普通方法功能, 通常使用public修饰

 

 

// DefaultClass是默认权限修饰的类: 使用范围本包中使用
class DefaultClass {
    // 默认权限成员变量
    String name = "李四";
    // 默认权限方法
    void fun(){
        System.out.println("我是默认的方法fun");
    }
}
public class ProtectedClass {
    protected double height = 175;
    protected void sleep(){
        System.out.println("我是受保护的休眠方法" + height);
    }
}
public class PublicClass {
    public String sex = "女";

    public void happy(){
        System.out.println("happy" + sex);
    }
}
public class TestQuanXian {
    public static void main(String[] args) {
        // 1. 默认修饰的类型, 可以在本包中使用
        DefaultClass sc = new DefaultClass();
        sc.fun();
        System.out.println(sc.name);

        // 2. 受保护权限可以在本包中使用
        ProtectedClass pc = new ProtectedClass();
        System.out.println(pc.height);
        pc.sleep();
    }
}
import com.ujiuye.quanxian.ProtectedClass;

public class ProtectedClassSub extends ProtectedClass {
    // ProtectedClassSub子类继承到了父类中的两个受保护成员
    // double height = 175;  sleep方法
    // 这两个受保护在子类中相当于private使用
    public void useProtected(){
        System.out.println(height);
        sleep();
    }
}
//import com.ujiuye.quanxian.DefaultClass;

import com.ujiuye.quanxian.ProtectedClass;
import com.ujiuye.quanxian.PublicClass;

public class Test {
    public static void main(String[] args) {
        // 1. 测试默认权限不能在其他包中使用
       // DefaultClass sc = new DefaultClass();
       // System.out.println(sc.name);

        // 2. 测试受保护权限在外包子类之外不能使用
        ProtectedClass pc = new ProtectedClass();
        // pc.sleep();

        ProtectedClassSub pcs = new ProtectedClassSub();
        // pcs.sleep();
        // System.out.println(pcs.height);

        // 3. 测试公共修饰的类型可以任意使用, 没有限制
        PublicClass pub = new PublicClass();
        System.out.println(pub.sex);
        pub.happy();
    }
}

修饰符关键字:

private 私有: 封装特性

static 静态: 属于类,跟着类存储在方法区中静态区域中, 就只有一份, 可以被所有对象共享使用

final 最后的, 不可改变的: 修饰类, 修改方法, 修饰变量(常量)

默认权限在类中不写出来, 写了反而代码报错

protected

public

 

 

六. 匿名内部类

 

1、没有名字的内部类

2、匿名内部类的使用前提:

        匿名类:继承一个类

       匿名类:实现一个接口

1、格式:

       new 父类类名或者接口名() {

            父类方法的重写或者是接口内容的实现

}

2、本质:

  (1) 创建了一个类的子类对象、接口的实现类对象

  (2) 更强调关系的一种写法

5、内部类的名称总结:

       (1) 如果是有名字的内部类,类名【外部类名$内部类名】

       (2) 如果是没有名字的内部类,通过匿名内部类的顺序描述类名,第一个匿名内部类的名称【外部类名$1】,第二个匿名内部类类名【外部类名$2】

public class 匿名内部类 {
    public static void main(String[] args) {
        // 1. 匿名内部类可以作为一个类的子类对象存在
        /*
             new 类名(){// 大括号就表示类的子类实现过程
             };
         */
        new Animal(){
            @Override
            public void eat(){
                System.out.println("不同动物吃不同的实物");
            }
        }.eat();
    }
}

 

代码块总结

1、局部代码块:
- 作用
- 限定 定义在局部代码块的中变量的作用范围
- 优势
- 不仅仅是范围的限定,也是变量在内存中储存时间的限定,(使用完成后,局部代码块外无法再调用 内存回收)

2、构造代码块:在构造方法之前调用,通常用于提取无参构造跟有参构造公共代码

3、静态代码块
1. 可以给类型中的静态成员变量进行赋值
2. 静态代码块运行时机: 因为静态都属于类, 因此在当前类进入内存时候(进入方法区),JVM虚拟机主动调用
静态代码块一次
3. 静态代码块使用场景: 如果有代码只需要执行一次, 并且是在所有其他代码运行之前就执行, 那么这些逻辑
可以设计在静态代码块中
举例: 数据库,持久性的存储数据; 需要在交易开始之前, 保证数据库连接成功的
(登录数据库,读取数据库登录时用户名和密码)
连接数据库的过程就可以设计在静态代码块中

内部类总结


1、普通成员内部类
- 定义位置
- 类中,方法外,跟成员变量同级的位置

- 访问方式
1) 内部类可以直接使用外部类包括的私有属性和方法
2) 外部类访问普通内部类必须通过对象 (类中)
// 1)
Wrapper war = new Wrapper();
Wrapper.Inner inn = war.new Inner();
// 2)
Wrapper.Inner inn2 = new Wrapper().new Inner();


2、私有的成员内部类
- 定义位置 跟普通成员内部类的区别是 前面加上private
- 访问方式:
1) 在外部类以外,不能直接访问外部类中的私有成员内部类
2) 可以在外部类中,定义一个访问私有成员内部类的公有方法,
让外界可以调用公有方法,间接的访问外部类中的私有成员内部类。


3、静态的成员内部类
- 定义位置,也是一个成员内部类,在成员内部类前面加上一个static关键字
- 访问方式:
1) 是外部类的静态成员,所以可以直接类名.静态内部类 使用
2) 如果需要调用 静态类的成员,需要观察静态内部类的成员是否是静态的,
如果是静态的可以直接调用,非静态则需要创建对象调用。

static class StaticInner {
public String name3 = "静态成员内部类-公有局部变量";
private String name33 = "静态成员内部类-私有局部变量";
static String name333 = "静态成员内部类-静态局部变量";

public String getName33() {
return name33;
}

public void staticMethod() { // 静态的成员内部类方法
System.out.println("静态的成员内部类方法");
}
}

Wrapper.StaticInner inn3 = new Wrapper.StaticInner();
System.out.println(Wrapper.StaticInner.name333); // 静态内部类静态属性
System.out.println(inn3.getName33()); // 静态内部类私有属性
System.out.println(inn3.name3); // 静态内部类公有属性
inn3.staticMethod(); // 静态内部公有有方法

4、局部内部类
- 定义位置: 局部内部类是定义在方法中的类
- 访问方式:
1) 局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用
2) 该类可以直接访问外部类的成员,也可以访问方法内的局部变量

public void localFunc() {
String name4 = "局部变量";

class LocalInner{
private String name5 = "局部内部类";

public String getName4() {
return name4;
}
}
// 局部内部类无法在 外部使用,只能在方法中创建对象使用,可以使用方法的局部变量
LocalInner l = new LocalInner();
l.getName4();
}


public class Demo_局部内部类 {
public static void main(String[] args) {
breath();
}

public static void breath(){
// 1. count作为局部变量不能单独获取到, 只能跟着breath方法运行使用
int count = 10;
// 2. 局部内部类, 与局部变量类似,只能在方法中定义使用
class Fei{
String color = "black";
public void show(){
System.out.println("每天吸" + count + "跟烟,总有一天肺就会变成" + color);
}
}
// 3. 局部变量,直接在方法中创建对象使用
Fei f = new Fei();
System.out.println(f.color);
f.show();
}
}

 

posted @ 2022-03-07 19:45  晴天般的微  阅读(83)  评论(0)    收藏  举报