初识java内部类
内部类:指的是在Java中可以将一个类定义在另一个类的内部。
- 内部类可以定义在 类的内部 (与类成员层次一致)
- 内部类可以定义在 方法/块内部 (与类成员相差一个层次,与方法的局部变量是一个层次)
*1.成员内部类
将一个类直接定义在类的里面,作为成员,与属性或方法层次一致。
成员内部类可以与正常类一样 使用不同的修饰符(权限的 ,特征的都行)来修饰
外部类只能使用两种权限修饰符,(public ,默认不写)
而内部类可以使用全部的四种权限修饰符,(public, protected ,默认不写 ,private)
好处1.省略了一个.java源文件
好处2.成员内部类中可以访问外部类的所有成员 ,包括私有的
public class Demo {
private String name = "这是正常类中的属性";
public void testDemo(){
System.out.println("这是正常类中的方法");
}
//成员内部类
public class InnerDemo{
public void testInnerDemo(){
System.out.println("我是成员内部类的方法"+name);
testDemo();
}
}
}
public static void main(String[] args) {
//创建内部类的对象---调用内部类的方法
Demo.InnerDemo innerDemo = new Demo().new InnerDemo();
//调用内部类的方法
innerDemo.testInnerDemo();
}
输出结果:
若想要在内部类中通过对象.的方式调用外部类成员,方式为: 外部类.this.外部类成员;
public class Demo {
private String name = "这是正常类中的属性";
public void testDemo(){
System.out.println("这是正常类中的testDemo方法");
}
//成员内部类
public class InnerDemo{
private String name = "我是内部类的属性";
public void testDemo(){
System.out.println("这是内部类中的testDemo方法");
}
public void testInnerDemo(){
System.out.println("我是成员内部类的testInnerDemo方法:"+name);//这个name就是内部类的
//如果想要访问外部类的name属性,应该这样写:
System.out.println("我是成员内部类的方法:"+Demo.this.name);
testDemo();
Demo.this.testDemo();
}
}
}
public static void main(String[] args) {
//创建内部类的对象---调用内部类的方法
Demo.InnerDemo innerDemo = new Demo().new InnerDemo();
//调用内部类的方法
innerDemo.testInnerDemo();
}
输出结果:
内部类存在后 源代码进行编译 产生一个字节码 Demo$InnerDemo.class
我们可以看出,美元符号
其实就是内部类命名的标志。
2.局部内部类
将一个类定义在方法/块里面,作为成员的内部结构,与临时的局部变量一个层次。
局部内部类是临时存在的,方法执行完,这个类的空间就被自动回收了。
局部内部类像是一个局部的变量一样,不能用public protected private及static
只能用abstract或final。
【小技巧】:在类中写一个空的main函数,让它去执行, 可以让该类立即被编译,生成.class文件。
局部内部类命名规则:
Demo$1InnerTestOneDemo
Demo$2InnerTestOneDemo
出现内部类重名以后,会有数字将它们区分开,1
表示第1次出现的内部类,2
表示第2次出现的内部类。
public class Demo {
private String name = "这是正常类中的属性";
public void testDemo(){
System.out.println("这是正常类中的testDemo方法");
}
public void testDemoOne(){
String s = "abc";
//在方法中定义一个局部内部类
class InnerTestOneDemo{
//局部内部类使用的变量都需要加final来修饰
}
}
{
//在块中定义一个局部内部类,与方法中那个内部类重名了
class InnerTestOneDemo{
//局部内部类使用的变量都需要加final来修饰
}
}
}
*局部内部类使用的变量只能是final修饰,为什么?
因为局部内部类是类加载的时候就编译好了,编译好的.class文件是不能改变的,如果局部内部类中的变量不使用final修饰,让变量随意去改变,就会产生冲突。
*3.匿名内部类
成员匿名内部类
局部匿名内部类
不用匿名内部类,以前我们这样写:
public interface Test {
public void test();
}
public class Son implements Test{
@Override
public void test() {
//······
}
}
public static void main(String[] args) {
Test t = new Son();
t.test();
}
有了匿名内部类以后,我们可以这样写:
public interface Test {
public void test();
}
public static void main(String[] args) {
Test t = new Test(){
public void test() {
//······
}
};//分号不可省略
}
new Test()后面的大括号里放的是匿名内部类的所有类成员。
通常接口或抽象类的具体子类这样写。
开发中为了省略一个类文件 , 上述写法比较常见。
匿名内部类很特殊, 只有类体, 没有类的( 修饰符 名字 继承 实现)。
不能用任何修饰符来修饰, 匿名内部类也没有构造方法。
应用:Swing 做一个按钮 ,绑定一个事件监听器
4.静态内部类
成员静态内部类
不需要外部类对象,通过正常的方式直接创建内部类即可!(前提是先导好包)
静态元素不能访问非静态成员(自己类和外部类的非静态成员都不行)。
public class Demo {
//静态内部类
public static class InnerDemoStatic{
}
}
package innerclass;
import innerclass.Demo.InnerDemoStatic;
public class TestMain {
public static void main(String[] args) {
InnerDemoStatic innerStatic = new InnerDemoStatic();
}
}