Java面向对象--代码块(初始化块)和内部类
本篇博客介绍Java学习过程中类的成员之代码块(初始化块)和内部类的具体使用。
目录:
☍ 代码块(初始化块)
代码块的概述
☃ 代码块(或初始化块)的作用:对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博客༺ཌ༈君☠纤༈ད༻同步发布