内部类:
把类定义在其他类的内部,我们称之为内部类
内部类有哪些特点:
1、内部类可以访问外部类的成员,包括私有
2、外部类要想访问内部类的成员,必须要创建内部类的对象
class Outer{
private int num = 10;
class Inner{
public void show(){
System.out.println(num);
}
}
public void fun(){
// show();
//创建内部类对象
Inner inner = new Inner();
inner.show();
}
}
public class InnerClassDemo1 {
public static void main(String[] args) {
Outer outer = new Outer();
// outer.show();
outer.fun();
}
}
内部类位置
成员位置(成员内部类)
局部位置(局部内部类)
class Outer2{
//定义在成员的位置上(成员内部类)
class Inner2{
}
public void fun(){
//定义在局部范围内(局部内部类)
class Inner3{
}
}
}
public class InnerClassDemo2 {
}
成员内部类:
1、定义在类的成员的位置上
2、内部类可以访问外部类的成员,包括私有
正确创建成员内部类对象的格式:
外部类名.内部类名 对象名=new 外部类名().new 成员内部类名();
class Outer3{
private int num = 10;
class Inner{
public void show(){
System.out.println(num);
}
}
}
public class InnerClassDemo3 {
public static void main(String[] args) {
//需求:我现在要想在测试类中访问到Inner类中的show方法,咋办,就必须得创建对象
// Inner inner3 = new Inner();
//正确创建成员内部类对象的格式
//外部类名.成员内部类名 对象名 = new 外部类名().new 成员内部类名();
// Outer3.Inner oi3 = new Outer3().new Inner();
// oi3.show();
Outer3 outer3 = new Outer3();
Outer3.Inner inner = outer3.new Inner();
inner.show();
}
}
成员内部类常见的修饰符:
private:其他类不能直接创建内部类的对象,要想使用被private修饰的类,就要间接的使用方法调用内部类的方法
static:内部类如果是被static修饰的时候,只能访问外部类中的成员
当内部类被静态修饰的时候,创建内部类的另一种方式:
外部类名.内部类名 对象名=new 外部类名.内部类名();
class Outer4 {
// private int num = 200;
private static int num = 200;
// private class Inner4{
// public void fun(){
// System.out.println(num);
// }
// }
static class Inner4 {
public static void fun() {
System.out.println(num);
}
}
// public void show() {
// Inner4 inner4 = new Inner4();
// inner4.fun();
// }
}
public class InnerClassDemo4 {
public static void main(String[] args) {
// Outer4.Inner4 oi4 = new Outer4().new Inner4();
// oi4.fun();
// Outer4 outer4 = new Outer4();
// outer4.show();
// Outer4.Inner4 oi4 = new Outer4.new Inner4();
//当内部类是被静态所修饰的时候,出现了另外一种创建内部类的方式
//格式如下:
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
// Outer4.Inner4 oi4 = new Outer4.Inner4();
// oi4.fun();
//直接通过类名直接调用
Outer4.Inner4.fun();
}
}
局部内部类:
1、定义在方法中的类
2、局部内部类可以直接用外部类中的所有成员
3、在局部内部类中引用的本地变量是最终变量(存在局部内部类的方法中定义局部变量自动加上final关键字)
在jdk1.8之后加上final
class Outer6{
private int num = 10;
public void fun(){
int num2 = 20;//无法修改值,因为前面有一个final修饰
class Inner6{
int num3 = 300;
public void show(){
num3 = 30;
//在局部内部类中引用的本地的变量必须是最终变量或者实际上的最终变量
//通过反编译工具观察发现,存在局部内部类的方法中定义的局部变量自动加上了final关键字
//在JDK1.8之后会自动加上final关键字
// num2 = 22;
num = 44;
System.out.println(num);
System.out.println(num2);
System.out.println(num3);
}
}
Inner6 inner6 = new Inner6();
inner6.show();
}
}
public class InnerClassDemo6 {
public static void main(String[] args) {
Outer6 outer6 = new Outer6();
outer6.fun();
}
}
匿名内部类
语句定义格式:
new 类名(可以是抽象类也可以具体的类)/接口(){
要重写的方法;
};匿名内部类对象
interface Inter{
public abstract void show();
public abstract void show2();
}
//class B implements Inter{
//
// @Override
// public void show() {
//
// }
//
// @Override
// public void show2() {
//
// }
//}
//Inter i = new B()
class Outer7{
public void fun(){
//使用匿名内部类的形式创建对象调用show方法
new Inter(){
@Override
public void show() {
System.out.println("这是show方法");
}
@Override
public void show2() {
System.out.println("这是show2方法");
}
}.show();
//使用匿名内部类的形式创建对象调用show2方法
new Inter(){
@Override
public void show() {
System.out.println("这是show方法");
}
@Override
public void show2() {
System.out.println("这是show2方法");
}
}.show2();
System.out.println("======================================");
//想一想,我现在的接口中,只有两个方法,方法的个数比较少,没调用一个方法,都要new一下,并且new之后的内容都是一样的
//如果以后接口中的方法很多的时候,你再用这样的方法,就会很麻烦
//怎么改进呢?
//利用接口多态的形式给匿名内部类起名字
Inter inter = new Inter(){
@Override
public void show() {
System.out.println("这是show方法");
}
@Override
public void show2() {
System.out.println("这是show2方法");
}
};
inter.show();
inter.show2();
}
}
public class InnerClassDemo7 {
public static void main(String[] args) {
Outer7 outer7 = new Outer7();
outer7.fun();
}
}
匿名内部类存在的前提:
要存在一个类或者是一个接口,这个类可以是具体的类也可以是抽象的类
利用接口多态为匿名内部类取个名字接收
匿名内部类在开发中的使用
调用一个方法后继续调用方法,说明第一个方法是有返回值的
匿名内部类:
1、有参构造方法参数是接口类型的时候
interface Outer11{
public abstract void fun();
}
//有参构造方法参数是接口类型的时候
class Inter11{
Outer11 outer11;
Inter11(Outer11 outer11){
this.outer11=outer11;
}
}
//有参构造方法的作用就是初始化变量
public class InterfaceDemo11 {
public static void main(String[] args) {
//使用接口多态为方法初始化
Outer11 outer11=new Outer11() {
@Override
public void fun() {
System.out.println("xuexi");
}
};
outer11.fun();
}
}
2、当成员方法的参数是接口类型的时候
interface Outer12{
public abstract void fun();
}
//当成员方法的参数是接口类型的时候
class Inter12{
Outer12 outer12;
public void show(Outer12 outer12){
outer12.fun();
}
}
public class InterfaceDemo12 {
public static void main(String[] args) {
Inter12 inter12=new Inter12();
inter12.show(new Outer12() {
@Override
public void fun() {
System.out.println("学习");
}
});
}
}
3、当返回值类型是接口的成员方法的时候
interface Outer13{
public abstract void fun();
}
//当返回值类型是接口的成员方法的时候
class Inter13{
Outer13 outer13;
public Outer13 show(){
Outer13 outer13=new Outer13() {
@Override
public void fun() {
System.out.println("学习");
}
};
return outer13;
}
}
public class InterfaceDemo13 {
public static void main(String[] args) {
Inter13 inter13=new Inter13();
//inter13.outer13.fun();NullPointerException这个时候调用的是Inter13中的fun方法而不是返回值里面的fun方法
inter13.show().fun();
}
}