内部类
一个类中包含另一个类
- 成员内部类
- 局部内部类(匿名内部类)
成员内部类
定义代码:
public class DemoInerClass { //外部类
class NewClass{//成员内部类
public void newMethod(){
System.out.println("我是内部类!");
System.out.println("我叫"+name+"多少岁"+age);//可以访问外部类中的成员变量
}
}
private String name;
private int age;
//外部类方法
public void method(){
System.out.println("我是外部类方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
使用代码:
间接使用
在外部类的方法当中使用内部类,然后main使用外部类的方法。
//外部类方法,再外部类的方法中创建内部类对象,再调用内部类方法
public void method(){
System.out.println("我是外部类方法");
//间接使用内部类的方法
NewClass newClass = new NewClass();
newClass.newMethod();
}
//main方法所在类
public class Demo {
public static void main(String[] args) {
DemoInerClass demoInerClass = new DemoInerClass();
demoInerClass.setAge(10);
demoInerClass.setName("小花");
demoInerClass.method();//调用外部类方法间接使用内部类方法
}
}
直接使用
外部类.内部类 对象名 = new 外部类().new NewClass();
对象名不能访问外部类的成员变量和方法,只能访问内部类的成员变量和方法
public class Demo {
public static void main(String[] args) {
DemoInerClass.NewClass demo = new DemoInerClass().new NewClass();
DemoInerClass demoOne = new DemoInerClass();
demo.newMethod();
}
}
内部类未编译时:
内部类编译后的情况:
变量名重名问题
代码解释如下:
public class Outer {
int num = 10;//外部类成员变量
public class Inner{
int num = 20;//内部类成员变量
public void method()
{
int num = 30;//内部类方法的局部变量
System.out.println(num);//30
System.out.println(this.num);//20
System.out.println(Outer.this.num);//10
}
}
}
public class OuterDemo {
public static void main(String[] args) {
Outer.Inner obj = new Outer().new Inner();//注意格式
obj.method();
}
}
结果:
"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=62487:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo09.OuterDemo
30
20
10
局部内部类
一个类定义在方法内部,只有当前的方法可以用它,出了这个方法就不能用了。
代码解释:
public class Out {//外部类
public void outMethod()
{
class In{//局部内部类
int num = 10;
public void inMethod()
{
System.out.println(num);//10
}
}
In in = new In();
in.inMethod();
}
}
public class DenoOut {
public static void main(String[] args) {
Out out = new Out();
out.outMethod();
}
}
结果:
"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=62718:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo08.DenoOut
10
Process finished with exit code 0
类的修饰符
类 | 用什么修饰? |
---|---|
外部类 | public/default |
成员内部类 | public/default/protected/private |
局部内部类 | 什么都不写 |
注意事项
局部内部类访问所在方法的局部变量,这个变量必须是有效final的(从Java 8+开始只要局部变量事实不变,可以省略final)所谓有效final:值不能变
具体原因:生命周期(谁活得久的问题)
1、new出来的对象再堆内存中
2、局部变量是跟着方法走的,在栈内存中
3、方法运行之后立刻出栈,局部变量立刻消失
4、new出来的对象会持续存在,直到垃圾回收
public class Out {//外部类
public void outMethod()
{
int num = 10;
final int one = 20;//Java 8+之后可省略final
//num = 30;//此时如果再给num赋值,则报错。
class In{//局部内部类
public void inMethod()
{
System.out.println(num);//10
System.out.println(one);//20
}
}
In in = new In();
in.inMethod();
}
}
匿名内部类(没有名字)
如果接口的实现类(或者父类的子类)只需使用唯一的一次,那么这种情况下就可以省略掉该类的定义,改为使用【匿名内部类】
有如下接口:
public interface NewInter {
void method();
}
普通实现方式:使用类NewInterImpl去实现接口NewInter–>在main方法中调用。代码如下:
public class NewInterImpl implements NewInter {
@Override
public void method() {
System.out.println("实现接口的抽象方法!");
}
}
public class New {
public static void main(String[] args) {
NewInter newInterImpl = new NewInterImpl();
newInterImpl.method();
//多态实现
NewInter obj = new NewInterImpl();
obj.method();
}
}
"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=60960:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo10.New
实现接口的抽象方法!
实现接口的抽象方法!
Process finished with exit code 0
利用匿名内部类实现:则可省略接口的实现类。
public class New {
public static void main(String[] args) {
NewInter obg = new NewInter() {
@Override
public void method() {
System.out.println("实现接口的抽象方法!");
}
};
obg.method();
}
}
"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=60970:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo10.New
实现接口的抽象方法!
Process finished with exit code 0
对匿名内部类格式的解析
new 接口名称(){......}
1.new 代表创建对象的动作。
2.接口名称就是匿名内部类要实现哪个接口。
3.{…}匿名内部类的真正内容。
注意事项
1.匿名内部类,在【创建对象】的时候,只能使用唯一 次。如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。
2.匿名对象,在【调用方法】的时候,只能调用唯一次。如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
**强调:匿名内部类和匿名对象不是一回事! ! ! **
即匿名对象又是匿名内部类:
new NewInter() {
@Override
public void method() {
System.out.println("实现接口的抽象方法!");
}
}.method();