• Java面向对象--代码块(初始化块)和内部类


    本篇博客介绍Java学习过程中类的成员之代码块(初始化块)和内部类的具体使用。


    目录:

    ☍ 代码块(初始化块)

    ☍ 内部类(Inner class)


    ☍ 代码块(初始化块)

    代码块的概述

    ☃ 代码块(或初始化块)的作用:对Java类或对象进行初始化操作

    ☃ 代码块(或初始化块)的分类:一个类中代码块只能被static修饰符修饰,若由static修饰称为静态代码块(static block),没有使用static修饰的,为非静态代码块

    ☃ static 代码块化 通常用于初始化static

    class Person{
    	public static String nation;
    	static{
    		nation = "China";
    	}
    }
    

    静态代码块:用static修饰的代码块

    ➊ 可以有输出语句

    ➋ 可以对类的属性、类的声明进行初始化操作

    ➌ 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。

    ➍ 若有多个静态的代码块,那么按照从上到下的顺序依次执行。

    ➎ 静态代码块的执行要先于非静态代码块。

    ➏ 静态代码块随着类的加载而执行,且只执行一次。

    静态代码块:用static修饰的代码块

    ➊ 可以有输出语句。

    ➋ 可以对类的属性、类的声明进行初始化操作。

    ➌ 除了调用非静态的结构外,还可以调用静态的变量或方法。

    ➍ 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。

    ➎ 随着对象的创建而执行,创建一次执行一次。且先于构造器执行。

    public class BlockTest {
    	public static void main(String[] args) {
    		String desc = Person.desc;
    		System.out.println("index:" + Person.index);
    		System.out.println("index:" + Person.index);
    		Person person = new Person();
    		System.out.println("index:" + Person.index);
            Person person = new Person();
    		System.out.println("index:" + Person.index);
    		System.out.println(person.toString());
    	}
    }
    
    class Person{
    	//属性
    	static String name;
    	int age;
    	static int index = 10;
    	static String desc = "人类";
    	//构造器
    	public Person() { }
    	//非静态代码块
    	{
    		age = 19;   //可以使用静态属性和非静态属性
    		name = "张三";
    		index++;
    		System.out.println("not static block");
            getInfo();  //可以调非静态方法和静态方法
            eat();
    	}
    	//静态代码块
    	static {
            //	age = 20;  不能使用非静态变量
    		name = "李四";
    		index++;
    		System.out.println("static block");
            getInfo();
            //	eat();   不能使用非静态方法
    	}
    	//方法
    	public void eat() {
    		System.out.println("吃饭");
    	}
    	public static void getInfo() {
    		System.out.println("我是一个快乐的人");
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    }
    /*输出和说明
    static block   //静态代码块随着类的加载而执行,只执行一次
    我是一个快乐的人
    index11	
    index11
    not static block	//随着对象的创建而执行
    我是一个快乐的人
    吃饭
    index12
    not static block	 //创建一个对象执行一次
    我是一个快乐的人
    吃饭
    index13
    Person [name=张三, age=19]   //非静态的代码块晚于静态代码执行
    */
    

    程序中成员变量赋值的执行顺序


    ☍ 内部类(Inner class)

    内部类概述

    ☃ 内部类是Java的五大成员之一,当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

    ☃ 在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。

    ☃ Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。

    ☃ Inner class的名字不能与包含它的外部类类名相同。

    ☃ 内部类可分为成员内部类(static成员内部类和非static成员内部类)以及局部内部类(不谈修饰符)、匿名内部类

    成员内部类

    class 外部类{
    	//成员变量声明
        //成员方法声明
        //构造器声明
        class 成员内部类{
        }
    }
    

    ☃ 可以将成员内部类看成外部类的成员(类似一个成员方法)或者是外部类中的一个类,同时具有成员和类的部分特性。

    ☃ 和外部类(只能声明为public 或者省略默认)不同,Inner class还可以声明为private或protected;

    ☃ 可以调用外部类的结构

    ☃ Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量;

    ☃ 可以在内部定义属性、方法、构造器等结构

    ☃ 可以声明为abstract类 ,因此可以被其它的内部类继承

    ☃ 可以声明为final的

    ☃ 编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)

    注意:

    ➥ 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员

    ➥ 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式

    ➥ 成员内部类可以直接使用外部类的所有成员,包括私有的数据

    ➥ 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的

    局部内部类

    //声明局部内部类
    class 外部类{
        //声明在方法体中
    	方法(){
    		class 局部内部类1{
    		}
    	}
        //声明在代码块内
    	{
    		class 局部内部类2{
    		}
    	}
        //声明在构造器中
        public 外部类名(){
        	class 局部内部类3{
    		}
        }
    }
    

    ☃ 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方
    都不能使用该类

    ☃ 但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型

    public class InnerClassTest{
        //开发中很少使用
        public void method(){
            //局部内部类
            class AA{
                //....
            }
        }
        //常见使用方式
        //返回了一个实现了Comparable节后的类的对象
        public Comparable getComparable(){
            //创建一个实现了Comparable接口的类:局部内部类
            class MyComparable implements Comparable{
                @Override
                public int compareTo(Object o){
                    //....
                    return 0;
                }
            }
            return new MyComparable();
        }
    }
    

    局部内部类特点:

    ☄ 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和(符号,如:Person)PetDog.class ,局部内部类还会加上数字编号,如:Person$1AA.class。

    ☄ 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类。

    ☄ 局部内部类可以使用外部类的成员,包括私有的。

    ☄ 局部内部类可以使用外部方法的局部变量,但是必须是final的,jdk7之前必须声明final关键字,jdk之8之后可以省略final关键字,但是一旦在局部类中使用了该变量,系统就会默认该变量为final的。由局部内部类和局部变量的声明周期不同所致。常用于Android开发。

    static void method1(){
    	int num1= 1;
    	//num1++; 报错    
    	 class BB{
    		int a = 1;
    		public int add() {			
    //jdk7之前必须将num1定义为final的,否则编译不通过,jdk8之后会默认为final
    			num1 = 10;
    			a += num1;
    			return a;
    		}
    	}
    	 //num1 ++;  报错
         //二选一,如果在内部类之后使用,内部类就不能使用,
    	 //内部类中一旦使用就会默认该变量为final的,之后就不可以修改了
    }
    

    ☄ 局部内部类和局部变量地位类似,不能使用public,protected,default,private

    ☄ 局部内部类不能使用static修饰,因此也不能包含静态成员

    内部类的使用

    创建成员内部了的实例化对象:

    //创建静态成员内部类实例
    外部类.内部类 变量名 = new 外部类.内部类构造器(参数列表);
    OutClass.InnerClass o1 = new OutClass.InnerClass();
    //创建非静态成员内部类实例
    外部类 外部类对象变量名 = new 外部类构造器(参数列表);
    OutClass out = new OutClass();
    外部类.内部类 变量名 =  外部类对象变量名.new 内部类构造器(参数列表);
    OutClass.InnerClass o2 = out.new InnerClass();
    

    内部类调用成员:

    ☄ 如果内部类与外部类成员不重名直接调用,但是要注意static关键字的限制

    ☄ 如果内部类与外部类成员重名了,则直接使用变量名/方法名调用的是内部类方法中的局部变量,若没有局部变量效果相当于this.变量名/this.方法名,调用的是内部类的成员

    ☄ 如果调用外部类的成员,对于外部类的静态成员使用外部类.成员名方式调用,对于非静态外部类成员,使用外部类.this.成员名的方式调用

    匿名内部类

    ☃ 匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

    ☃ 格式:

    new 父类构造器(实参列表)or 实现接口(){
    	// 匿名内部类的类体部分
    } 
    

    匿名内部类特点:

    ☄ 匿名内部类必须继承父类或实现接口

    ☄ 匿名内部类只能有一个对象

    ☄ 匿名内部类对象只能使用多态形式引用

    public class InnerClassTest{
        ////匿名内部类(实现了Comparable接口),并将对象方法
        public Comparable getComparable(){
            //创建一个实现了Comparable接口的类:局部内部类
                   return new Comparable() {
            	 @Override
                 public int compareTo(Object o){
                     //....
                     return 0;
                 }
    		};
        }
    }
    

    本博客与CSDN博客༺ཌ༈君☠纤༈ད༻同步发布

  • 相关阅读:
    P4343 [SHOI2015]自动刷题机
    P1083 [NOIP2012 提高组] 借教室
    [AGC记录] AGC003题解
    [做题记录-乱做] [AGC003E] Sequential operations on Sequence
    [AGC记录] AGC002题解
    [AGC记录] AGC001题解
    [做题记录-乱做] [AGC001F] Wide Swap
    [做题记录-计数] [ARC087D] Squirrel Migration
    [做题记录-计数] [九省联考2018]秘密袭击coat
    [做题记录-计数][AGC024E] Sequence Growing Hard
  • 原文地址:https://www.cnblogs.com/asio/p/12534049.html
Copyright © 2020-2023  润新知