文章目录
一、基本含义
1.1 含义
将类1放在类2的内部,类1叫做内部类,类2叫做类1外部类。
1.2 作用
(1)封装性更强。除了outer类,其他类都不能访问(包含同包其它类)。
(2)inner类可以访问outer类所有成员(包含私有成员)。反之,不可。
(3)便捷性。inner类实现的功能,使用outer类也可实现,只是有时不方便。
二、内部类成员
2.1 成员内部类——普通inner类+ 静态inner类
2.1.1 含义
是outer类的一个成员。
普通内部类:修饰词为public。
public class OuterClass {
// 成员内部类。即普通内部类。
public class InnerClass{
name = "张三";
age = 18;
public InnerClass(){
}
}
}
静态内部类:修饰词为public + static。
public class OuterClass {
// 静态内部类。
public static class InnerClass{
name = "张三";
age = 18;
public InnerClass(){
}
}
}
2.1.2 使用
public class OuterClass {
private String name;
private int age;
public int age() {
return age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void outerShow1() {
System.out.println("外部类方法");
}
public OuterClass() {
}
public OuterClass(String name, int age) {
this.name = name;
this.age = age;
}
// 普通内部类。可以直接访问outer类的成员。
public class InnerClass {
String name = "李四";
public InnerClass() {
age = 18; // 普通内部类可以直接使用outer类的属性
}
public void show() {
System.out.println("姓名1:" + getName() + ";年龄:" + getAge()); // age和getAge()效果等价。
System.out.println("姓名2:" + name + ";年龄:" + age); // 属性调用:就近原则。
System.out.println("姓名3:" + OuterClass.this.name + ";年龄:" + age);// getName()和OuterClass.this.name效果等价。
}
}
// 静态内部类。不可以直接访问非静态成员。
public static class InnerClass2 {
String name = "李四";
public InnerClass2() {
}
public void show() {
System.out.println("外部类name=" + new OuterClass().name + ",内部类name=" + name);
}
}
// 方法内部类。
public void showInnerClass() {
String name1 = "王五";
// 方法内部类。只能在本方法内使用。无类修饰符。
class InnerClass3{
String name = "赵柳";
public void print(){
System.out.println("方法name1=" + name1 +",方法内部类name=" + name);
}
}
InnerClass3 i = new InnerClass3();
i.print();
}
// 外部类使用内部类。
public static void main(String[] args) {
// 普通内部类的调用。
OuterClass o = new OuterClass("张三", 23); // 1. 创建外部类对象。
InnerClass i = o.new InnerClass(); // 2. 创建内部对象。
i.show(); // 3. 内部对象调用内部属性和内部方法。
// 静态内部类的调用。
InnerClass2 i2 = new InnerClass2(); // 1. 创建内部对象。
i2.show(); // 2.内部对象调用内部属性和内部方法。
// 方法内部类的调用。
OuterClass o2 = new OuterClass(); // 1. 创建外部类对象。
o2.showInnerClass();
}
}
2.2 局部内部类——普通局部内部类 + 匿名内部类
2.2.1 普通局部内部类
含义:是方法或作用域中的一个成员。
适用场景:想创建一个类辅助,又不想其是公共可用的。
生命周期:方法和属性中。
(1)方法中
public class OutClass{
private int num1 = 1;
private static int num2 = 2;
private int num5 = 5;
public void show(){
int num3 = 3; //不能加 private
// 方法中的内部类。
class InnerClass{ //不能加访问修饰符
private int num4 = 4;
private int num1 = 10;
public void showInner(){
// 外部类属性
System.out.println(num1);// 标识符相同时,就近原则。
System.out.println(OutClass.this.num1); // 标识符相同时,调用外部类num1的方法。
System.out.println(num2);//本来需要OutClass.num2修饰的,但是JDK8不需要。内部类是static class时需要
System.out.println(num5);//可以直接访问外部类私有变量
// 方法属性。
System.out.println(num3);
// 内部类属性。
System.out.println(num4);
}
}
//在方法内,创建内部类实例对象,并调用内部类方法或属性。
InnerClass inner = new InnerClass();
inner.showInner();
}
}
(2)作用域中
public class OutClass2{
public void show(){
int num = 2;
if(num == 2){
class InnerClass{
public void showInner(){
System.out.println("可以创建作用域中内部类!");
}
}
InnerClass inner = new InnerClass();
inner.showInner();
} else{
System.out.println("不可创建作用域中内部类!");
}
}
}
(3)Test类:
public class Test{
public static void main(String []args){
OutClass out = new OutClass();
out.show();
OutClass2 out2 = new OutClass2();
out2.show();
}
}
2.2.2 匿名内部类——常用
项目 | 含义 |
---|---|
含义 | 没有名字的内部类 |
修饰符 | 无 |
使用场景 | 主要用于不能直接创建对象的抽象类和接口 |
成员 | 无静态成员,无构造函数。 |
格式一:
类名/接口/抽象类 对象名 = new 类名/接口/抽象类(){
// 匿名内部类类体。
// 属性
// 方法体
};
对象名.方法名();
格式二:
new 类名/接口/抽象类(){
// 匿名内部类类体。
}.方法名();
实体类——人类:
public class Person{
private String name;
public String getName(){
return name;
}
public Person(){
}
public Person(String name){
this.name = name;
}
public void eat(){
System.out.println("人们");
}
}
实体类——学生类:
public class Student extends Person{
private int clazz;
public int getClazz(){
return clazz;
}
public Student(){
}
public Student(String name, int clazz){
super(name);
this.clazz = clazz;
}
public void eat(){
System.out.println("学生");
}
}
抽象类——动物抽象类:
public abstract class Animal{
public abstract void bark();
}
实体类——狗类:
public class Dog extends Animal{
public void bark() {
System.out.println("汪汪");
}
}
接口——运动接口:
public interface Sportable{
public abstract void sport();
}
2.2.2.1 实体类创建
相当于创建该类的一个子类对象。
public class Test {
public static void main(String[] args) {
Student stu=new Student("张三",3);
System.out.println(stu.getClass());
// 结果:class dayPractice.Student
// 通过实体类创建匿名内部类对象。
Person p = new Person(){
public void eat(){
System.out.println("通过实体类创建匿名内部类对象");
}
}; // 分号不能省略。
p.eat(); // 结果:通过实体类创建匿名内部类对象
System.out.println(p.getClass());
// 结果:class dayPractice.Test$1
2.2.2.2 抽象类创建
相当于定义了该抽象类的一个子类对象,并重写了抽象类中所有的抽象方法。
public class Test {
public static void main(String[] args) {
Dog dog=new Dog(); // 正常创建实体对象
dog.bark(); // 结果:汪汪
// 通过抽象类创建匿名内部类对象。
Animal an=new Animal(){
public void bark(){
System.out.println("汪汪汪");
}
};
an.bark(); // 结果:汪汪汪
//返回的是包名加类名
System.out.println(an.getClass());
// 结果 class dayPractice.Test$2
2.2.2.3 实体类创建
相当于定义了该接口的一个实现类对象,并重写了接口中所有的抽象方法。
public class Test {
public static void main(String[] args) {
// 通过接口创建匿名内部类对象。
Sportable s = new Sportable(){
public void sport(){
System.out.println("打篮球");
}
};
s.sport();// 结果:打篮球
System.out.println(s.getClass());
// 结果:class dayPractice.Test$3
// 方式二:
new Sportable(){
public void sport(){
System.out.println("打篮球2");
}
}.sport();
// 结果:打篮球2
}
}
三、创建内部类
1.3 使用外部类元素
包含:属性,方法,以及使用.this与.new。
特点:可以无限制地访问外围类的元素。
public class OuterClass {
private String name ;
private int age;
public String getName(){
return name;
}
public String getAge(){
return age;
}
public void setName(String name){
this.name = name;
}
public void setAge(String age){
this.age = age;
}
/**
* 内部类
* (1)在内部类中:可以直接使用外围类的元素。与修饰符无关。
* (2)在内部类中:使用直接this调用外部元素。
*/
public class InnerClass{
public InnerClass(){
name = "张三"; // 直接使用外围类的属性。
age = 18;
}
public void show(){
/**
* 直接使用外围类的属性。如name和getName()效果等价。
*/
System.out.println("姓名:" + getName() +";年龄:" + getAge());
System.out.println("姓名2:" + name +";年龄:" + getAge());
}
// 同过this,可以直接调用外部类的所用元素。
public OuterClass getOuterClass(){
return OuterClass.this; // 返回外部类元素。
}
}
public void outerShow1(){
System.out.println("内部类,可以通过.this调用外类所用元素");
}
public static void main(String[] args) {
/**
* 主函数中使用内部类。
* 第一步:创建外部类实例对象。
* 语法:外类名 外类对象名 = new 外类构造器名();
* 第二步:通过外部类创建内部类。
* 语法:外类名.内类名 内类对象名 = 外类对象名.new 内类构造器名();
* 第三步:调用内部类方法。
* 语法:内部对象名.内部类方法名。
*/
// 创建外部类实例对象。
OuterClass outerClassObject = new OuterClass();
// 通过外部类调用内部类。
OuterClass.InnerClass innerClassObject = outerClassObject.new InnerClass();
/**
* 调用内部类方法。
*/
innerClassObject.show();
/**
* 调用外部类元素
* 通过在内部类中创建getOuterClass()方法,调用所有外类元素。
* (1)调用外部类属性
* (2)调用外部类方法
*/
// 调用外部类属性
String strName = innerClassObject.getOuterClass().getName();
System.out.println(strName); // 张三。
// 调用外部类方法
innerClassObject.getOuterClass().outerShow();
}
}