内部类
一、定义:将一个类A定义在一个类B中,这个类A称之为内部类
二、分类:
成员内部类:将类定义在一个类中的成员位置上,相当于外部类的一个成员
局部内部类:将类定义在一个方法中
三、访问特点:
内部类可以直接访问外部类的成员,包括私有和静态。
class Outer1{
int a1 = 10;
private int a2 = 11;
public static int a3 = 12;
class Inner1{
public void fun1(){
// a1 = 20;
System.out.println(a1);
// a2 = 30;
System.out.println(a2);
// a3 = 40;
System.out.println(a3);
}
}
}
public class InnerDemo1 {
public static void main(String[] args) {
//外部类类名.内部类类名 对象名 = new 外部类类名().new 内部类类名();
Outer1.Inner1 inner1 = new Outer1().new Inner1();
inner1.fun1();
}
}
四、成员内部类的常见修饰符:
private 为了保证数据的安全性
static 为了让数据访问更方便
被静态修饰的成员内部类只能访问外部类的静态成员
内部类被静态修饰后的方法
静态方法
非静态方法
(1)内部类修饰符为静态时
package com.shujia.day10.ketang.bao6;
/*
内部类常用的修饰符:
static
private
*/
class Outer2{
static int a1 = 10;
private static int a2 = 11;
public static int a3 = 12;
static class Inner1{
public void fun1(){
System.out.println(a1);
System.out.println(a2);
System.out.println(a3);
}
}
}
public class InnerDemo2 {
public static void main(String[] args) {
Outer2.Inner1 inner1 = new Outer2.Inner1();
inner1.fun1();
}
}
(2)当内部类修饰符为私有时
package com.shujia.day10.ketang.bao6;
class Outer3 {
private class Inner {
public void fun1(){
System.out.println("好好学习,天天向上!");
}
}
public void show(){
Inner inner = new Inner();
inner.fun1();
}
}
public class InnerDemo2 {
public static void main(String[] args) {
Outer3 outer3 = new Outer3();
outer3.show();
}
}
结论:通过内部类中写的公共成员show()方法,使外部类的对象来调用,也就间接调用了私有的方法
外部类要访问内部类的成员,必须创建对象。
拓展题(在控制分别输出:30,20,10)
package com.shujia.day10.ketang.bao6;
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num); // 30
System.out.println(this.num); // 20
System.out.println(Outer.this.num); // 10
}
}
}
public class InnerDemo3 {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
五、局部内部类
可以直接访问外部类的成员
可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
局部内部类访问局部变量的注意事项:如果局部内部类中要使用方法中的局部变量的话,这个变量会被使用final关键字进行修饰 final int a = 10;
package com.shujia.day10.ketang.bao6;
class Outer4 {
//成员方法
public void fun1() {
//局部变量
int a = 10; // 如果局部内部类中要使用方法中的局部变量的话,这个变量会被使用final关键字进行修饰
//局部内部类
class Inner {
int b = 20;
public void show() {
// a = 11; // 从内部类引用的本地变量必须是最终变量或实际上的最终变量
b = 12;
System.out.println(a);
System.out.println(b);
}
}
Inner inner = new Inner();
inner.show();
}
}
public class InnerDemo4 {
public static void main(String[] args) {
Outer4 outer4 = new Outer4();
outer4.fun1();
}
}
六、为什么必须被final修饰?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用final修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下。
七、匿名内部类
就是内部类的简化写法。
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:
/*
匿名内部类:
语法定义格式:
new 抽象类/接口(){
//要重写的方法
}
本质:
是一个继承了类或者实现了接口的子类匿名对象
package com.shujia.day10.ketang.bao8;
abstract class Demo1{
public abstract void fun1();
}
//class Demo1Zi1 extends Demo1{
// @Override
// public void fun1() {
// System.out.println("hello world");
// }
//}
//
//class Demo1Zi2 extends Demo1{
// @Override
// public void fun1() {
// System.out.println("hello");
// }
//}
class Student1{
public void show1(Demo1 demo1){
demo1.fun1();
}
}
public class NiMingClassDemo1 {
public static void main(String[] args) {
Student1 student1 = new Student1();
// student1.show1(new Demo1Zi());
// student1.show1(new Demo1Zi2());
/**
* 相当于jvm给我们做了几件事情
* 1、jvm底层自己造了一个类继承抽象类或者实现接口,这个类没有名字
* 2、重写的方法(实现的方法),我们只需要关注重写的方法
* 3、将这个类的对象造出来
*/
student1.show1(new Demo1() {
@Override
public void fun1() {
System.out.println("hello");
}
});
student1.show1(new Demo1() {
@Override
public void fun1() {
System.out.println("hello world");
}
});
}
}
package com.shujia.day10.ketang.bao8;
interface Inter1{
public abstract void fun1();
}
//class Inter1Impl implements Inter1{
// @Override
// public void fun1() {
// System.out.println("hello java");
// }
//}
class Student2{
public void show(Inter1 inter1){
inter1.fun1();
}
}
public class NiMingClassDemo2 {
public static void main(String[] args) {
Student2 student2 = new Student2();
// student2.show(new Inter1Impl());
student2.show(new Inter1(){
@Override
public void fun1(){
System.out.println("hello linux");
}
});
student2.show(new Inter1(){
@Override
public void fun1(){
System.out.println("hello java");
}
});
}
}
匿名内部类在开发中的使用
package com.shujia.day10.ketang.bao8;
//要求在控制台输出”HelloWorld”
interface Inter {
void show();
}
//class InterImpl implements Inter{
// @Override
// public void show() {
// System.out.println("HelloWorld");
// }
//}
class Outer {
//补齐代码
public static Inter method(){
return new Inter() {
@Override
public void show() {
System.out.println("HelloWorld");
}
};
}
}
public class OuterDemo {
public static void main(String[] args) {
//我们从调用的方式可以得到一个结论,发现method这个方法是可以被Outer类直接调用的,说明method类是静态的
//method方法没有参数
//调用method方法之后紧跟着可以接着调用show()方法
//说明method方法调用完后返回的应该是一个对象,而且是一个实现了Inter接口类的对象,method方法的返回值类型是Inter类型
Outer.method().show();
}
}
标签:内部,void,System,public,println,new,class
From: https://www.cnblogs.com/zhuzhuya/p/18349816