
类的五大成员:属性,方法,构造方法,代码块,内部类 在 Java 等面向对象编程语言中,内部类(Inner Class)是定义在另一个类内部的类。它与外部类(包含它的类)存在紧密关联,能够访问外部类的成员变量和方法,包括私有成员。 看下面代码:
\\这个就是外部类
public class Outer {
//这个就是内部类
public class Inner{
}
}
//外部其他类
class Outer1{
}那大家思考一个问题,我们为什么要学习内部类的,他的适应场景是什么呢? 那写一个描述汽车的类
public class Car{
String carName;
int carAge;
int carcolor;
int engineAge;
String engineName;
}
//大家看这个代码,这是我们是不是可以把这个Engine可以提出一个类
public class Car{
String carName;
int carAge;
int carcolor;
//内部类
//内部类的表示是没有任何实际意义的
class engine{
int engineAge;
String engineName;
}
}内部类的访问特点:
public class Car {
private String carName; // 外部类私有成员
int carAge; // 外部类成员
// 发动机内部类
class Engine {
private String engineName;
int engineAge;
// 内部类方法可以直接访问外部类的所有成员(包括私有)
public void showCarInfo() {
System.out.println("汽车名称:" + carName); // 访问外部类私有成员
System.out.println("汽车使用年限:" + carAge);
}
public void setEngineInfo(String name, int age) {
engineName = name;
engineAge = age;
}
}
// 外部类方法访问内部类成员,必须先创建内部类对象
public void showEngineInfo() {
Engine engine = new Engine(); // 创建内部类对象
System.out.println("发动机名称:" + engine.engineName);
System.out.println("发动机使用年限:" + engine.engineAge);
}
public void setCarName(String name) {
this.carName = name;
}
public static void main(String[] args) {
// 创建外部类对象
Car car = new Car();
car.carAge = 5;
car.setCarName("特斯拉Model 3");
// 创建内部类对象(需通过外部类对象)
Car.Engine engine = car.new Engine();
engine.setEngineInfo("永磁同步电机", 5);
// 调用内部类方法
engine.showCarInfo();
// 调用外部类方法(该方法内部访问了内部类成员)
car.showEngineInfo();
}
}内部类分为四大类:成员内部类,静态内部类,局部内部类,匿名内部类
定义:直接定义在外部类的成员位置(与成员变量、成员方法同级),没有static修饰。 定义格式:
public class Outer{
String name ;
int age;
class inner {
String name;
int age;
}
}public class Outer{
protected class inner {
}
}特性:
public class Outer {
private int outerField = 10;
// 成员内部类
public class Inner {
int innerField = 20;
public void innerMethod() {
// 直接访问外部类成员
System.out.println("外部类字段:" + outerField);
}
}
// 外部类访问内部类成员
public void outerMethod() {
Inner inner = new Inner(); // 必须创建内部类对象
System.out.println("内部类字段:" + inner.innerField);
}
public static void main(String[] args) {
Outer outer = new Outer();
// 创建内部类对象:外部类对象.new 内部类()
Outer.Inner inner = outer.new Inner();
inner.innerMethod(); // 调用内部类方法
}
}方式1: 在外部类中编译使用内部类的方法,对外提供内部类的对象
public class Phone {
private String brand;
// 内部类:电池
class Battery {
private int capacity;
public Battery(int capacity) {
this.capacity = capacity;
}
// 内部类方法:显示电池信息
public void showInfo() {
// 直接访问外部类成员
System.out.println(brand + "手机,电池容量:" + capacity + "mAh");
}
}
// 外部类构造方法
public Phone(String brand) {
this.brand = brand;
}
// 对外提供内部类对象的方法
public Battery createBattery(int capacity) {
return new Battery(capacity); // 创建并返回内部类对象
}
public static void main(String[] args) {
Phone phone = new Phone("华为");
// 通过外部类方法获取内部类对象
Phone.Battery battery = phone.createBattery(5000);
battery.showInfo();
}
}方式2: 直接创建格式:外部类名.内部类名 对象名字 = new 外部类().new 内部类();
// 完整语法结构
外部类名.内部类名 对象名 = new 外部类().new 内部类();这是因为成员内部类依赖于外部类的实例存在,必须先创建外部类对象,才能通过外部类对象创建内部类对象。
public class Outer {
class Inner {
void show() {
System.out.println("这是内部类方法");
}
}
public static void main(String[] args) {
// 在外部类的静态方法中创建内部类对象(也需要遵循同样规则)
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
// 在另一个完全独立的类中使用
class OtherClass {
public static void main(String[] args) {
// 外部其他类中创建内部类对象
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}注意:
这种方式仅适用于非静态成员内部类 静态内部类的创建方式不同,不需要依赖外部类实例:
静态内部类是用 static 修饰的内部类,它是内部类中比较特殊的一种,不依赖外部类的实例而存在,更像是一个 “嵌套在外部类中的独立类”。
创建静态内部类对象的格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名();
外部类名.内部类名 对象名 = new 外部类名.内部类名();调用静态内部类的格式: 先创建对象,后对象调用
// 访问静态内部类的静态变量
外部类名.静态内部类名.静态变量名;
// 调用静态内部类的静态方法
外部类名.静态内部类名.静态方法名(参数);通过对象访问静态内部类的非静态成员
// 创建对象后,调用非静态方法或访问非静态变量
对象名.非静态方法名(参数);
对象名.非静态变量名;核心特点
局部内部类是定义在外部类的方法或代码块(如if、for块)内部的类,其作用范围仅限于所在的方法或代码块,出了这个范围就无法访问。
局部内部类的特点:
public class Outer {
private String outerData = "外部类数据";
public void outerMethod() {
int methodParam = 100; // 方法局部变量
// 局部内部类(仅在当前方法内可见)
class LocalInner {
public void showInfo() {
System.out.println("访问外部类成员:" + outerData);
System.out.println("访问方法参数:" + methodParam);
}
}
// 必须在方法内部创建局部内部类对象并使用
LocalInner inner = new LocalInner();
inner.showInfo(); // 正确:在作用域内使用
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.outerMethod(); // 调用方法,间接触发局部内部类功能
// 以下代码会编译报错(外部无法访问局部内部类)
// LocalInner inner = new LocalInner(); // 错误:找不到LocalInner类
// Outer.LocalInner inner = new Outer().new LocalInner(); // 错误:LocalInner不可见
}
}public class Shop {
// 外部类私有成员(验证特性:局部内部类可访问)
private String shopName = "晨光文具店";
// 外部类非私有成员
int saleCount = 100;
// 包含局部内部类的方法
public void calculateDiscount(int originalPrice) {
// 方法局部变量:赋值后不修改(隐式final,验证特性2)
int discountRate = 90; // 9折
// 方法局部变量:显式final(验证特性2)
final int minPrice = 10;
// 局部内部类(验证:无public/private/static修饰符,特性3)
class DiscountCalculator {
// 局部内部类的成员方法
public void showFinalPrice() {
// 1. 访问外部类所有成员(包括私有,特性1)
System.out.println("店铺:" + shopName);
System.out.println("本月销量:" + saleCount + "件");
// 2. 访问方法的局部变量(final/隐式final,特性2)
int finalPrice = originalPrice * discountRate / 100;
System.out.println("原价:" + originalPrice + "元,折后价:" + finalPrice + "元");
System.out.println("最低售价限制:" + minPrice + "元");
// !若尝试修改局部变量,编译报错(验证特性2)
// discountRate = 80; // 报错:局部变量在内部类中使用,不能修改
// minPrice = 5; // 报错:final变量不能修改
}
}
// 外部无法直接访问,必须在方法内创建对象并使用(特性:作用域有限)
DiscountCalculator calculator = new DiscountCalculator();
calculator.showFinalPrice();
}
public static void main(String[] args) {
Shop shop = new Shop();
// 调用方法,间接触发局部内部类功能(外部无法直接操作局部内部类)
shop.calculateDiscount(50);
// !以下代码均编译报错(验证特性:外部无法直接访问,特性3)
// DiscountCalculator calc = new DiscountCalculator(); // 错误:找不到该类
// public class DiscountCalculator{} // 错误:局部内部类不能加public
// static class DiscountCalculator{} // 错误:局部内部类不能加static
}
}定义:匿名内部类本质就是隐藏了名字的内部类 匿名内部类是一种没有类名的局部内部类,通常用于 “一次性” 实现接口或继承类,简化代码编写。它在定义的同时必须创建实例,语法上更像是一个 “创建对象的表达式”。
格式:
接口类型 对象名 = new 接口名() {
// 必须实现接口中所有抽象方法
@Override
public 返回值类型 方法名(参数列表) {
// 方法体
}
};示例:
// 定义接口
interface Flyable {
void fly();
}
public class Test {
public static void main(String[] args) {
// 创建实现Flyable接口的匿名内部类
Flyable bird = new Flyable() {
@Override
public void fly() {
System.out.println("小鸟展翅高飞");
}
};
// 调用方法
bird.fly();
}
}父类类型 对象名 = new 父类名(构造参数) {
// 可选:重写父类方法
@Override
public 返回值类型 方法名(参数列表) {
// 方法体
}
};示例:
// 定义父类
class Person {
public void say() {
System.out.println("人在说话");
}
}
public class Test {
public static void main(String[] args) {
// 创建继承Person类的匿名内部类
Person student = new Person() {
@Override
public void say() {
System.out.println("学生说:我在学习");
}
};
// 调用重写后的方法
student.say();
}
}// 实现接口的简化写法
new Runnable() {
@Override
public void run() {
System.out.println("直接执行一次");
}
}.run(); // 直接调用方法关键语法要点:
这种格式的优势在于:当某个类只需要使用一次时,无需单独定义类文件,直接在使用处完成定义和实例化,大幅简化代码。