骖六龙行御九州之第十二天——代码块、包、修饰符、内部类

一、代码块

  • 什么是代码块

    • 代码块是类的成分之一:成员变量,方法,构造器,代码块,内部类

标准类{
    成员变量;
    构造方法;
    成员方法;
    代码块;
    内部类;
​
}
  • 代码块在Java中如何表示

    • 在Java中,使用{}括起来的代码成为代码块(Code block)

  • 代码块的分类
  • 根据其位置和声明的不同,可以分为:

    • 局部代码块:用于限定变量生命周期,及早释放,提高内存利用汇率

    • 静态代码块:主要用于对静态属性进行初始化

    • 实例(构造)代码块:调用构造方法都会执行,并且在构造方法前执行

    • 同步代码块:一种多线程保护机制

  • 局部代码块

    • 在方法中出现,可以限定变量生命周期,及早释放,提高内存利用率。

    • {}出现在方法内,那么该大括号就被称为局部代码块

package 局部代码块;
​
public class Demo {
    public static void main(String[] args) {
        //局部代码块
        {
            int a = 100;
        }
        //{}出现在方法内,那么该大括号就被称为局部代码块
        //在方法中出现,可以限定变量生命周期,及早释放,提高内存利用率。
    }
}
  • 静态代码块

    • 必须有static修饰,必须放在类中方法外

    • 与类一起加载执行,并且静态代码块只执行一次

    • 给静态成员初始化

public class Test {
    public static void main(String[] args) {
        A a = new A(100);
    }
}                                 //寻常给静态成员赋初始化值
class A{
    static int a =100; //构造方法
    public  A(){}
    public  A(int a){
        this.a=a;
    }
}
package 静态代码块;
​
public class Test {
    public static void main(String[] args) {
        System.out.println(A.a);
    }
}                               //静态代码块给变量赋初始化值
class A{
    static int a ;
    static {
         a =100;   //不需要再定义int
        System.out.println("我是静态代码块");
    }
}
  • 特点

    • 每次执行类,加载类的时候都会先执行静态代码块一次

    • 静态代码块是自动触发执行的,只要程序启动静态代码块就会先执行一次

    • 在启动程序之前可以做资源的初始化,一般用于初始化静态资源。

  • 实例代码块

    • 没有static修饰,必须放在类中方法外。

    • 与对象初始化一起加载

    • 即每次调用构造方法都会执行,并且在构造方法前执行。

package 构造代码块;
​
public class Demo {
    public static void main(String[] args) {
        new A();
        new A();
    }
}
class A{
    public A(){
        System.out.println("A");
    }
    {
        System.out.println("我是构造方法代码块");
    }
}
  • 特点

    • 无static修饰。属于对象,与对象的创建一起执行的。

    • 每次调用构造器初始化对象,实例代码块都要自动触发执行一次。

    • 实例代码块实际上是提取到每一个构造器中去执行的。

    • 实例代码块中的内容在构造方法前执行。

  • 注意:

    • 类的成员定义,和顺序无关

  • 静态代码块、构造代码块、构造函数执行顺序
  • 父类静态代码块>子类静态代码块>main()方法>父类代码块>父类构造器>子类代码块>子类构造器

    • 静态代码块:类的加载。字节码文件进代码区

    • main: JVM自动的调用main方法

    • 代码块、构造器:初始化过程(创建对象过程)

package 代码快运行顺序;
​
public class Demo extends A {
    public static void main(String[] args) {
        System.out.println("我是main方法");
        Demo demo = new Demo();
        System.out.println("我第二次的mian方法");
        Demo demo1 = new Demo();
    }
    static {
        System.out.println("我是子类静态代码块");
    }
    {
        System.out.println("我是子类构造代码块");
    }
    public  Demo(){
        System.out.println("我是子类的构造器");
    }
}
class A{
    static {
        System.out.println("我是父类静态代码块");
    }
    {
        System.out.println("我是父类构造代码块");
    }
    public  A(){
        System.out.println("我是父类的构造器");
    }
}
  • 同步代码块

    • 多线程才遇到

二、包

  • 什么是包?

    • 包就是文件夹==根据包名自动生成class文件的存放路径

    • 类如果有package关键字,运行或者使用类的时候,就不能只写类名了;要写包名+类名:全限定路径名

  • 包的三大作用

    • 区分相同名字的类。同一个文件夹下不能出现同名的文件,因此把两个同名的类分别放在两个包中,就相当于是放在两个文件夹中。

    • 当类很多时,可以方便的管理类。

    • 控制访问范围。权限修饰符

  • 包的基本语法

  • package是关键字,表示打包;后面的是包名。必须代码的第一行

package java.util;
  • 使用包中的类

    • 以ArrayList类为例,如果想要使用java.util中的ArrayList类,有两种方式:

    • 使用import,即放一个import语句在文件的最前面:

    • 格式:

      • import 包名.类名;

package a.b;
import x.y.A;
public class Demo{
    public static void main(String[] args) {
​
        A a = new A();
        System.out.println(a);
    }
}
    • 直接在程序中打出ArrayList的全名,不管在哪里,只要使用了就打出全名。

package a.b;
//import x.y.A;
public class Demo{
    public static void main(String[] args) {
​
        x.y.A a = new x.y.A();
        System.out.println(a);
    }
}
  • 包的命名规则

  • 只能包含数字、字母、下划线和“.”,但是不能用数字开头,不能是关键字;合法的标识符

    • demo.class.ex1 //错误的!因为class是关键字

    • demo.12a.ex1 //错误的!因为12a是数字开头

    • demo.a12.ex1 //正确的!

  • 命名规范

  • 一般都是小写字母+“.”。

  • 普遍的命名方式都是:公司域名倒写.项目名.业务模块名

    • eg: com.sina.crm.user //用户模块

    • com.sina.crm.order //订单模块

    • com.sina.crm.utils //工具类

  • 常见包

  • java.lang //lang包是基础包,默认引入,不需要再引入

  • java.util //util包是系统提供的工具包,里面有很多工具类

  • java.net //网络包,用于网络开发的

  • java.awt //是做java的界面开发,GUI

  • java.sql //数据库

三、修饰符 :Java :类 变量 方法

  • 什么是修饰符?

    • 修饰符用来修饰 类、方法、变量

    • 通常放在语句的最前端

  • 修饰符的分类

    • 权限(访问)修饰符

    • 非权限修饰符

  • 访问修饰符

  • Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问(使用、赋值、取值、调用)。Java支持4种不同的访问权限。

    • public:公有访问。对所有的类都可见。

    • protected:保护型访问。对同一个包可见,对不同的包的子类可见。

    • default:默认访问权限。只对同一个包可见,注意对不同的包的子类不可见。

    • private:私有访问。只对同一个类可见,其余都不见。

  • 非访问权限修饰符

  • 常用的有以下几种:

    • static 修饰符:不能修饰类;只能修饰 方法 变量

    • final 修饰符,用来修饰类、方法和变量

      • final 修饰的类不能够被继承

      • 修饰的方法不能被继承类重新定义

      • 修饰的变量为常量,是不可修改的。

    • abstract修饰符,用来创建抽象类和抽象方法。

    • synchronized 用于多线程的同步。

    • volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

    • transient:序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。

  • 修饰符作用

类修饰符

外部类修饰符

  • public(访问控制符),将一个类声明为公共类,它可以被任何对象访问,一个程序的主类必须是公共类。

  • default(访问控制符),类只对包内可见,包外不可见。

  • abstract(非访问控制符),将一个类声明为抽象类,抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充,抽象类可以包含抽象方法和非抽象方法。

  • final(非访问控制符),将一个类生命为最终(即非继承类),表示它不能被其他类继承。

注意:

protected 和 private 不能修饰外部类,是因为外部类放在包中,只有两种可能,包可见和包不可见。

final 和 abstract不能同时修饰外部类,因为该类要么能被继承要么不能被继承,二者只能选其一。

不能用static修饰,因为类加载后才会加载静态成员变量。所以不能用static修饰类和接口,因为类还没加载,无法使用static关键字。

内部类修饰符

  • 内部类与成员变量地位一直,所以可以public、protected、default和private,同时还可以用static修饰,表示嵌套内部类,不用实例化外部类,即可调用

方法修饰符

  1. public(公共控制符),包外包内都可以调用该方法。

  2. protected(保护访问控制符)指定该方法可以被它的类和子类进行访问。

  3. default(默认权限),指定该方法只对同包可见,对不同包(含不同包的子类)不可见。

  4. private(私有控制符)指定此方法只能有自己类等方法访问,其他的类不能访问(包括子类),非常严格的控制。

  5. final,指定方法已完备,不能再进行继承扩充。

  6. static,指定不需要实例化就可以激活的一个方法,即在内存中只有一份,通过类名即可调用。

  7. synchronize,同步修饰符,在多个线程中,该修饰符用于在运行前,对它所属的方法加锁,以防止其他线程的访问,运行结束后解锁。

  8. native,本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的。

  9. abstract,抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。==抽象方法不能被声明成final 和 static。==任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。抽象方法的声明以分号结,例如:public abstract sample(); 。

变量修饰符

  • 成员变量修饰符

  1. public(公共访问控制符),指定该变量为公共的,它可以被任何对象的方法访问。

  2. protected(保护访问控制符)指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。

  3. default(默认权限),指定该变量只对同包可见,对不同包(含不同包的子类)不可见。

  4. private(私有访问控制符)指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。

  5. final,最终修饰符,指定此变量的值不能变。

  6. static(静态修饰符)指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。

  7. transient(过度修饰符)指定该变量是系统保留,暂无特别作用的临时性变量。不持久化。

  8. volatile(易失修饰符)指定该变量可以同时被几个线程控制和修改,保证两个不同的线程总是看到某个成员变量的同一个值。

  • 注意:final 和 static 经常一起使用来创建常量。

  • 局部变量修饰符

    • 只能使用 final 修饰局部变量

      • 为什么不能赋予权限修饰符?

        • 因为局部变量的生命周期为一个方法的调用期间,所以没必要为其设置权限访问字段,既然你都能访问到这个方法,所以就没必要再为其方法内变量赋予访问权限,因为该变量在方法调用期间已经被加载进了虚拟机栈,换句话说就是肯定能被当前线程访问到,所以设置没意义。

      • 为什么不能用static修饰?

        • 我们都知道静态变量在方法之前先加载的,所以如果在方法内设置静态变量,可想而知,方法都没加载,你能加载成功方法内的静态变量?

接口修饰符

  • 接口修饰符

    • 接口修饰符只能用public、default和abstract,不能用final、static修饰。

    • 接口默认修饰为abstract。

  • 接口中方法修饰符

    • 只能用 public abstract修饰,当然如果你什么都不写,默认就是public abstract。

    • 注意:在Java1.8之后,接口允许定义具体方法了

      • static

      • default

四:内部类

  • 什么是内部类

  • 将一个类定义在另一个类的里面或者定义在一个方法的内部,把该类就称之为内部类;内部类也是对封装的一种体现。

  • 类中定义类

package 内部类1;
​
public class Demo {
}
class A{
    class B{   //B为内部类
        
    }
}
  • 注意

  1. 定义在class 类名{}花括号外部的,即使是在一个文件里,也不能称为内部类

  2. 内部类和外部类共用同一个java的源文件,但是经过编译之后,内部类会形成自己单独的字节码文件;

    1. $

  • 内部类分类

  • 根据内部类定义位置的不同,可以将内部类分为

    • 成员内部类

      • 而成员内部类又根据是否被static修饰分为

        • 普通内部类

        • 静态内部类;

    • 局部内部类

    • 匿名内部类

  • 成员内部类

    • 普通内部类

  • 未被static修饰的成员内部类就称为普通内部类;

package 普通内部类;
​
public class Demo {
}
class A{
    //类中方法外
    class B{
        
    }
}
  • 初始化内部类格式

    • 成员

      • 属性

      • 行为

外部类.内部类  变量名 = new 外部类().new 内部类()
package 内部类;        //初始化类的使用
​
public class Demo {
    public static void main(String[] args) {
        A.B v =new A().new B();
        System.out.println(v.a);
        v.m();
    }
}
class  A{
    class B{
        int a =100;
        public void m(){
            System.out.println("十步杀一人,千里不留行");
        }
    }
}

总结:

  • 外部类中的任何成员都可以在普通内部类方法中直接被访问

  • 普通内部类所处的成员与外部类成员位置相同,因此也受public、private等访问限定符的约束;其他类

  • 在内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,需采用:

外部类名称.this.同名成员名 
  • 普通内部类对象必须在先有外部类对象前提下才能被创建;

  • 外部类中不能直接访问内部类中的成员,如果要访问必须先要创建内部类的对象;

  • 注意

    • 在Java中,所有的变量定义,可以写在类中方法外

    • 但是,其他代码(操作)必须要有代码承载

  • 静态内部类

  • 被static修饰的内部成员类就称为静态内部类;

package 静态内部类;
​
public class out {  //out是外部类
    static int a ;
    static int b ;   //静态成员变量b
​
    public void methodA(){
        a=10;
        System.out.println(a);
    }
​
    public static void methodB(){
        System.out.println(b);
    }
   //in就是静态内部类
    static class in{
       public void methodInner(){
           // 在内部类中只能访问外部类的静态成员变量及方法
           // a=100; 编译失败,原因:a不是外部类中的静态成员变量
           // methodA(); //编译失败,原因:methodA()不是静态类成员方法
           b=100;
           methodB();
       }
       public static void main(String[] args) {
           //静态成员变量访问:类名.成员变量名
           System.out.println(out.b);
​
           // 静态内部类对象的创建
           //不需要借助外部类对象
           in ic=new in();
           // 静态成员方法访问
           ic.methodInner();
       }
    }
}
  • 局部内部类(不常用)

定义在外部类的方法体或者代码块{}中,该种内部类只能在其定义的位置进行使用,其他位置均不能使用;

总结:

  • 局部内部类只能在所定义的方法体内部使用;

  • 不能被public、static等修饰符修饰;

  • 不能在局部内部类中定义静态成员;

  • 局部内部类不能被public、static等访问限定符修饰,若加上修饰符,就会报错

  • 匿名内部类

  • 匿名内部类,就是没有名字的一种嵌套类。它是Java对类的定义方式之一。

package 匿名内部类;
​
public class Demo {
​
}
class  A{
    public void m(){
        new A(){
            public void ma() {
                System.out.println();
            }
        };
    }
}
  • 为什么要使用匿名内部类

    • 快速实例化接口或者抽象类

    • package 匿名内部类使用;

      public class Demo {
          public static void main(String[] args) {
             A a= new A(){
                  @Override
                  public void m() {
                      System.out.println("封狼居胥");
                  }
              };
             a.m();
              B b = new B(){
                  @Override
                  public void n() {
                      System.out.println("想当年,金戈铁马,气吞万里如虎");
                  }
              };
              b.n();
          }
      }
      interface A{
          public void m();

      }
      abstract class B{
          public abstract void n();
      }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值