一.代码块
1.分类
-
静态代码块
- 在类中方法外使用static修饰的代码块
- 在调用类时即会被执行(使用类名调用静态成员或创建类的对象)
- 静态代码块只会被执行一次
-
构造代码块
- 在类中方法外直接使用大括号{}括住代码
- 每次创建对象时都会被调用一次
-
局部代码块
- 在方法中用大括号{}括住代码
- 每次执行到局部代码块都会重新创建,一旦执行完立刻被销毁,声明周期只局限与局部代码块
- 局部代码块可以访问外部的成员,但是外部无法访问局部代码块中定义的成员
-
同步代码块
2.执行顺序
- 静态代码块>构造代码块>构造方法
3.例子
package com.codepart;
public class Test {
public static void main(String[] args) {
A.show2();
A a1=new A();
a1.show();
A a2=new A();
/*输出结果*/
/*
* 静态代码块
* 静态方法
* 构造代码块
* 构造方法
* 1
* 构造代码块
* 构造方法
* */
}
}
class A{
//顺序1:静态代码块
static{
System.out.println("静态代码块");
}
//顺序2:构造代码块
{
System.out.println("构造代码块");
}
//顺序3:构造方法
public A(){
System.out.println("构造方法");
}
public void show(){
int num1=1;
//局部代码块
{
System.out.println(num1);
int num2=2;
}
//这里无法访问代码块内部定义的变量
//System.out.println(num2);
}
public static void show2(){
System.out.println("静态方法");
}
}
一.内部类
1.成员内部类
- 概述
在类中定义的另一个类就是成员内部类
- 特点
- 成员内部类其实就是外部类的一个成员(跟成员属性和方法一样),可用private、protected修饰
- 访问
- 成员内部类可以直接通过外部类成员名称访问所有外部类成员(包括私有成员),如遇到同名需要加上
外部类名.this.
作为前缀 区分外部类和内部类成员 - 外部类访问内部类成员需要先创建内部类对象
- 其他类访问内部类,需要先创建外部类对象,再根据外部类对象创建内部类对象,而且内部类声明要加上
外部类名.
作为前缀
- 成员内部类可以直接通过外部类成员名称访问所有外部类成员(包括私有成员),如遇到同名需要加上
2.静态内部类
- 概述
使用static修饰的成员内部类就是静态内部类
- 访问
- 静态内部类可以访问外部类静态成员和静态内部类的所有成员,不可以访问外部类非静态成员
- 外部类访问内部类成员依然需要先创建内部类对象
- 其他类访问内部类,直接通过外部类名创建静态内部类对象,而且内部类声明要加上
外部类名.
作为前缀
package com.innerclass;
public class Test1 {
public static void main(String[] args) {
//1.访问成员内部类
//先创建外部类对象
OuterA oa=new OuterA();
//再根据外部类对象创建内部类对象(声明时需要带上外部类名的前缀)
OuterA.InnerA ia=oa.new InnerA();
ia.print();
oa.printA();
//2.访问静态内部类
//直接通过外部类名创建静态内部类对象
OuterA.InnerB ib=new OuterA.InnerB();
ib.print1();
//静态内部类中的静态成员可以直接访问
OuterA.InnerB.print2();
oa.printB();
}
}
class OuterA{
int num=1;
private int age=18;
static String name="张三";
//成员内部类可以使用private、protected修饰
protected class InnerA{
int num=2;
public void print(){
int num=3;
System.out.println("方法局部变量:"+num);
System.out.println("成员内部类属性:"+this.num);
//如需访问外部类同名成员,需要加上 [外部类名.this]
System.out.println("外部类属性:"+OuterA.this.num);
//成员内部类可以访问外部类的成员
System.out.println(age);
System.out.println(name);
}
}
public void printA(){
//外部类成员访问内部类成员需要创建内部类对象再访问
InnerA ia=new InnerA();
System.out.println("内部类属性:"+ia.num);
}
//静态内部类
static class InnerB{
int money=2;
public void print1(){
//静态内部类可以访问外部类静态成员和静态内部类的所有成员
System.out.println(name);
System.out.println(money);
}
public static void print2(){
System.out.println(name);
}
}
public void printB(){
//外部类成员访问静态类成员需要创建内部类对象再访问
InnerB ib=new InnerB();
ib.print1();
InnerB.print2();
}
}
2.局部内部类
- 概述
在方法体或者代码块中定义的类就是局部内部类
-
访问
- 访问权限仅限于方法体或代码块内
- 外部无法直接创建局部内部类对象,但方法可以返回内部类创建好的对象,然后在外部使用。(局部内部类需要继承父类或实现接口并且重写相应的方法)
-
注意
- 局部内部类访问外部的变量必须是常量final,因为方法体或代码块中定义的变量生命周期只限于方法体或代码块内,方法体或代码块执行完毕变量就会销毁,但是局部内部类可能还会继续被引用,无法再获取变量值。final相当于复制一份数据,而且数据不能改变(基本类型是值不变,引用类型是引用地址不变,但其成员值可以改变),保证了数据一致性(如果数据随意改变可能会出现跟预想不一样的结果)
package com.innerclass;
public class Test2 {
public static void main(String[] args) {
OuterB ob=new OuterB();
ParentClass pc= ob.getIc(1);
pc.print();
}
}
//抽象父类
abstract class ParentClass{
abstract void print();
}
class OuterB{
//返回局部内部类的对象(这里用了多态)
public ParentClass getIc(final int a){
//局部内部类访问外部变量需要加上final
final int b=2;
//局部内部类继承父类并重写方法
class InnerC extends ParentClass{
public void print(){
System.out.println(a);
System.out.println(b);
}
}
InnerC ic=new InnerC();
return ic;
}
}
2.匿名内部类
- 概述
继承父类或实现接口并重写方法的类就是匿名内部类
- 特点
- 匿名内部类使用了多态
- 匿名内部类常用作方法参数
package com.innerclass;
public class Test3 {
public static void main(String[] args) {
new ParentClassA(){
@Override
public void print() {
System.out.println("我是普通父类");
}
}.print();
new ParentClassB(){
@Override
public void print() {
System.out.println("我是抽象父类");
}
}.print();
//匿名内部类作为参数
show(new InterfaceC(){
@Override
public void print() {
System.out.println("我是接口");
}
});
}
public static void show(InterfaceC ic){
ic.print();
}
}
//普通父类
class ParentClassA{
public void print(){
System.out.println("......");
}
}
//抽象父类
abstract class ParentClassB{
public abstract void print();
}
//接口
interface InterfaceC{
public abstract void print();
}