- 就是在一个类中定义另一个类。 如: class A 中定义class B。 B 就是所谓的内部类。
- 位置: 最外面的类,相对里面的类来说叫做外部类,在类里,相当于局部定义的类,叫做内部类。
// 外部类
修饰符 class 类名{
//在类的内部定义的类叫做内部类。
修饰符 class 类名{
}
}
1.2 内部类分类
- 按照 位置 分为两种:
- 成员内部类: 在成员位置叫做 成员内部类
- 局部内部类 :在局部位置(即方法中)叫做 局部内部类
- 内部类,可以直接访问外部类中的 成员变量和方法,包括 private修饰的成员。
- 外部类,如果想访问内部类成员,就必须建立内部类的对象。
- 通过外部类创建方法创建内部类对象访问!
public class Demo {
public static void main(String[] args) {
//如何访问 Inter中的show()呢!?
Outer o = new Outer();
o.method(); //通过内部类对象。私有类也可以访问!
}
}
class Outer{
private String name ="谷凌爱";
class Inter{
//1.在类中能直接 sout(name)么?
//1.1 通过使用方法,访问属性name
public void show(){
System.out.println("name:"+ name); //访问外部类属性。
}
}
//2.通过外部类的方法创建内部类的对象。
public void method(){
//创建内部类对象!
Inter i = new Inter();
i.show();
}
}
输出结果:
name:谷凌爱2.1 访问方式二(了解)
- 通过类调用直接访问。
public class Demo {
public static void main(String[] args) {
// Inter i = new Inter(); // 直接new肯定不行!因为是内部类!
//3.1 外部类.内部类 名字 = 外部对象.内部对象 ; //注意是外部对象,内部对象
//如果内部类是private的,将无法访问!
Outer.Inter oi = new Outer().new Inter();
oi.show(); // 可以直接方法内部类中的方法和属性
System.out.println("年龄: "+oi.age);
}
}
class Outer{
private String name ="谷凌爱";
class Inter{
int age = 18;
//1.在类中能直接 sout(name)么?
//1.1 通过使用方法,访问属性name
public void show(){
System.out.println("name:"+ name); //访问外部类属性。
}
}
}
输出结果:
name:谷凌爱 年龄183. 成员内部类 3.1 内部类被private修饰
- 内部类被private修饰,目的,就是 隐藏自己 不想被外界发现或者使用!
- 弊端也是显而易见的。
public class PrivateDemo {
public static void main(String[] args) {
//1.2 弊端:当你加了private之后 类调用的方法就失效了! 那用哪种方法!?
Person p = new Person();
p.show("屠夫");
}
}
class Person{
// 1.1 当加了私有private。注意:private修饰外界无法直接创建对象使用!
private class Heart{
//心脏方法
public void doSomeThing(){
System.out.println("心脏跳");
}
}
public void show(String name){ // 精髓在这 提供一个外部访问!
//加一个条件判断,控制逻辑。
if (name.equals("医生")){
new Heart().doSomeThing(); // 可以拿到方法。
}else{
System.out.println("不符合条件");
}
}
}
输出结果:
不符合条件3.2 被static修饰的内部类
- static只能修饰内部类(通常类是不允许声明为静态的)。
- 静态内部类,会整体看做一个静态成员。
public class Demo {
public static void main(String[] args) {
//3.访问内部类有2种方式,通过方法创建对象。
//3.1如果类没有被修饰private。
Outher.Inter i = new Outher.Inter();
i.show();
i.show2();
//3.2静态资源访问直接类名.方法名即可。链式加载!
Outher.Inter.show2();
//3.3 如果类有被修饰private。
Outher o = new Outher();
o.method();
}
}
// 外部类
class Outher{
//1.3 静态只能访问静态
private static String name ="谷爱凌";
//1.static 修饰的类,整体会看成一个静态成员。
static class Inter{
static int age=18;
//1.1 静态内部类中可以有普通方法
// 既然被看成一个整体,
public void show(){
System.out.println(name);
}
//1.2 静态内部类中也可以有静态方法
static public void show2(){
System.out.println(age); //1.2.1静态只能访问静态
}
}
//2.外部类方法
public void method(){
Inter i = new Inter();
i.show();
i.show2();// 普通方法可以访问静态方法,但是需要自己手写方法名称。
}
}
输出结果:
show: 谷爱凌 show2: 18 show2: 18 show: 谷爱凌 show2: 184. 局部内部类
- 在方法里的类。不常见!
public class Demo2 {
public static void main(String[] args) {
//2.匿名对象调用方法。
new Inter1().show();
}
}
class Inter1{
private String name = "谷爱凌";
public void show(){
class Outer1{
public void method(){
System.out.println("局部内部类");
}
}
//1.创建内部类对象,当调用方法时,调用一次!
new Outer1().method();
}
}
5. 匿名内部类
- 同 匿名对象 一样,没有名字 的内部类。就是为了调用一次。
new 接口/类名(){
1.重写方法
2.自定义方法
};
- 匿名对象和匿名内部类通常一起使用,属于局部内部类!
public class Demo {
public static void main(String[] args) {
Outer outer = new Outer();
outer.method(); // 2.1为什么没有调用成功!?
//3.直接调用普通类中的方法。也可以通过调用自定义方法
new Inter2(){
public void Inter2method(){
System.out.println("自定义方法!");
}
}.show2();
new Inter2(){
public void Inter2method(){
System.out.println("自定义方法!");
}
}.Inter2method();
//4.调用抽象类中的方法
Inter3 inter3 = new Inter3(){
@Override
public void show4() {
System.out.println("show4");
}
};
//4.1 可以选择调用不同的方法
inter3.show3(); // 调用父类方法!
//相当于创建对象调用,调用一次执行一次。
inter3.show4();
inter3.show4();
inter3.show4();
inter3.show4();
}
}
class Outer{
//1.匿名内部类?在什么位置!?
public void method(){
// 2.匿名内部类使用
new Inter(){
@Override
public void show() {
System.out.println("Inter接口中抽象方法");
}
}.show(); //2.2 相当于匿名对象,调用方法才可以!
}
}
//接口
interface Inter{
void show();
}
//普通类
class Inter2{
public void show2(){
System.out.println("show2");
}
}
abstract class Inter3{
//抽象类中的普通方法
public void show3(){
System.out.println("show3");
}
//抽象方法
abstract public void show4();
}
输出结果:
Inter接口中抽象方法 show2 自定义方法! show3 show4 show4 show4 show45.1.扩展 :匿名内部类使用场景
- 通过匿名对象作为参数传递。将1和2对比看。
public class Demo {
public static void main(String[] args) {
//2.1 使用匿名对象 不用写实现类,传递一次数据,执行完就释放!
method(new Animal() {
@Override
public void eat() {
//TODO 传递参数。
System.out.println("吃肉");
}
});
//1.实现接口,重写方法,创建对象,调用方法。执行完还在栈中!!
Lion lion = new Lion();
lion.eat();
}
//2静态方法,不会被重写!
public static void method(Animal a){
a.eat();
}
}
//接口
interface Animal{
void eat();
}
//1,实现接口,重写方法!
class Lion implements Animal{
@Override
public void eat() {
System.out.println("吃肉");
}
}



