内部类
概述
内部类是类的五大成分之一:成员变量,方法,构造器,代码块,内部类
概念:定义在一个类里面的类就是内部类
作用:提供更好的封装性,体现出组件思想,间接解决类无法多继承引起的一系列问题
分类:静态内部类、实例内部类(成员内部类)、局部内部类、匿名内部类(重点)
静态内部类
定义:有 static 修饰,属于外部类本身,会加载一次
静态内部类中的成分研究:
- 类有的成分它都有,静态内部类属于外部类本身,只会加载一次
- 特点与外部类是完全一样的,只是位置在别人里面
- 可以定义静态成员
静态内部类的访问格式:外部类名称.内部类名称
静态内部类创建对象的格式:外部类名称.内部类名称 对象名称 = new 外部类名称.内部类构造器
静态内部类的访问拓展:
- 静态内部类中是否可以直接访问外部类的静态成员? 可以,外部类的静态成员只有一份,可以被共享
- 静态内部类中是否可以直接访问外部类的实例成员? 不可以,外部类的成员必须用外部类对象访问
public class Demo{
public static void main(String[] args){
Outter.Inner in = new Outter.Inner();
}
}
static class Outter{
public static int age;
private double salary;
public static class Inner{
//拥有类的所有功能 构造器 方法 成员变量
System.out.println(age);
//System.out.println(salary);报错
}
}
实例内部类
定义:无 static 修饰的内部类,属于外部类的每个对象,跟着外部类对象一起加载
实例内部类的成分特点:实例内部类中不能定义静态成员,其他都可以定义
实例内部类的访问格式:外部类名称.内部类名称
创建对象的格式:外部类名称.内部类名称 对象名称 = new 外部类构造器.new 内部构造器
Outter.Inner in = new Outter().new Inner()
实例内部类可以访问外部类的全部成员
- 实例内部类中可以直接访问外部类的静态成员,外部类的静态成员可以被共享访问
- 实例内部类中可以访问外部类的实例成员,实例内部类属于外部类对象,可以直接访问外部类对象的实例成员
局部内部类
局部内部类:定义在方法中,在构造器中,代码块中,for 循环中定义的内部类
局部内部类中的成分特点:只能定义实例成员,不能定义静态成员
public class InnerClass{
public static void main(String[] args){
String name;
class{}
}
public static void test(){
class Animal{}
class Cat extends Animal{}
}
}
匿名内部类
匿名内部类:没有名字的局部内部类
匿名内部类的格式:
new 类名|抽象类|接口(形参){
//方法重写。
}
匿名内部类的特点:
- 匿名内部类不能定义静态成员
- 匿名内部类一旦写出来,就会立即创建一个匿名内部类的对象返回
- 匿名内部类的对象的类型相当于是当前 new 的那个的类型的子类类型
- 匿名内部类引用局部变量必须是常量,底层创建为内部类的成员变量(原因:JVM → 运行机制 → 代码优化)
public class Anonymity {
public static void main(String[] args) {
Animal a = new Animal(){
@Override
public void run() {
System.out.println("猫跑的贼溜~~");
//System.out.println(n);
}
};
a.run();
a.go();
}
}
abstract class Animal{
public abstract void run();
public void go(){
System.out.println("开始go~~~");
}
}
权限符
权限修饰符:有四种**(private -> 缺省 -> protected - > public )**
可以修饰成员变量,修饰方法,修饰构造器,内部类,不同修饰符修饰的成员能够被访问的权限将受到限制
四种修饰符访问权限 | private | 缺省 | protected | public |
---|---|---|---|---|
本类中 | √ | √ | √ | √ |
本包下的子类中 | X | √ | √ | √ |
本包下其他类中 | X | √ | √ | √ |
其他包下的子类中 | X | X | √ | √ |
其他包下的其他类中 | X | X | X | √ |
protected 用于修饰成员,表示在继承体系中成员对于子类可见
- 基类的 protected 成员是包内可见的,并且对子类可见
- 若子类与基类不在同一包中,那么子类实例可以访问其从基类继承而来的 protected 方法(重写),而不能访问基类实例的 protected 方法
代码块
静态代码块
静态代码块的格式:
static {
}
- 静态代码块特点:
- 必须有 static 修饰,只能访问静态资源
- 会与类一起优先加载,且自动触发执行一次
- 静态代码块作用:
- 可以在执行类的方法等操作之前先在静态代码块中进行静态资源的初始化
- 先执行静态代码块,在执行 main 函数里的操作
public class CodeDemo {
public static String schoolName ;
public static ArrayList<String> lists = new ArrayList<>();
// 静态代码块,属于类,与类一起加载一次!
static {
System.out.println("静态代码块被触发执行~~~~~~~");
// 在静态代码块中进行静态资源的初始化操作
schoolName = "张三";
lists.add("3");
lists.add("4");
lists.add("5");
}
public static void main(String[] args) {
System.out.println("main方法被执行");
System.out.println(schoolName);
System.out.println(lists);
}
}
/*静态代码块被触发执行~~~~~~~
main方法被执行
张三
[3, 4, 5] */
实例代码块
实例代码块的格式:
{
}
-
实例代码块的特点:
- 无 static 修饰,属于对象
- 会与类的对象一起加载,每次创建类的对象的时候,实例代码块都会被加载且自动触发执行一次
- 实例代码块的代码在底层实际上是提取到每个构造器中去执行的
-
实例代码块的作用:实例代码块可以在创建对象之前进行实例资源的初始化操作
public class CodeDemo {
private String name;
private ArrayList<String> lists = new ArrayList<>();
{
name = "代码块";
lists.add("java");
System.out.println("实例代码块被触发执行一次~~~~~~~~");
}
public CodeDemo02(){ }//构造方法
public CodeDemo02(String name){}
public static void main(String[] args) {
CodeDemo c = new CodeDemo();//实例代码块被触发执行一次
System.out.println(c.name);
System.out.println(c.lists);
new CodeDemo02();//实例代码块被触发执行一次
}
}