查漏补缺8--内部类、匿名内部类、匿名对象总结

本文详细解析了Java内部类的概念,包括成员内部类和局部内部类的使用场景,以及静态内部类和非静态内部类的区别。同时,介绍了匿名内部类的特性和应用场景,对比了其与局部内部类的差异,最后讲解了Lambda表达式的使用。

一、内部类
在内部类中再定义一个类的情况就是内部类, Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
内部类可以分为:成员内部类:定义在外部类中(静态成员内部类、非静态成员内部类)
局部内部类:定义在外部类的方法中,只存在

①成员内部类

class Outer {
    private int s;
    public class Inner {
        public void mb() {
            s = 100;
            System.out.println("在内部类Inner中s=" + s);
        }
    }
    public void ma() {
        Inner i = new Inner();
        i.mb();
    }
}
public class InnerTest {
    public static void main(String args[]) {
        Outer o = new Outer();
        o.ma();
    }
}

1)外部类访问内部类的成员,先要得到内部类或内部类对象(这里可以结合枚举类一起使用),然后通过“内部类.成员”或“内部类对象.成员”的方式
例如下面例子,访问Constant 的内部类AliMsgTemplate的方法

Constant.AliMsgTemplate aliMsgTemplate = Constant.AliMsgTemplate.getAliMsgTemplateByIndex(type.intValue());
public class Constant {
public enum AliMsgTemplate {
        MSG_REGISTER_CODE(REGISTER, "msg_register_code", "验证码${code},您正在注册成为新用户,感谢您的支持!"),
        VERIFICATION_CODE(MODIFY, "msg_verification_code", "验证码${code},您正在尝试修改登录密码,请妥善保管账户信息。"),
        MSG_ORDER_EVALUATE(ORDER_EVALUATE, "msg_order_evaluate", "您好!您的订单已服务完成,订单详情:${remark},请及时评价!谢谢!"),
        ORDER_PROCESS_CODE(ORDER_PROCESS, "msg_order_process", "您的订单已经在处理中,当前状态:${status},订单摘要:${remark},请耐心等待服务,谢谢!"),
        ORDER_PENDING_CODE(ORDER_PENDING, "msg_order_pending", "您有新的订单待处理,当前状态:${status},订单摘要:${remark},请及时处理。")
        ;

        private int index;

        private String key;

        private String template;

        private AliMsgTemplate(int index, String key, String template) {
            this.index = index;
            this.key = key;
            this.template = template;
        }

        public static AliMsgTemplate getAliMsgTemplateByIndex(int index) {
            for (AliMsgTemplate aliMsgTemplate : AliMsgTemplate.values()) {
                if (aliMsgTemplate.index == index) {
                    return aliMsgTemplate;
                }
            }
            return null;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getTemplate() {
            return template;
        }

        public void setTemplate(String template) {
            this.template = template;
        }
    }
}

2)成员内部类可以直接使用外部类的所有成员, 包括私有的数据(遵循静态类的引用规则:静态内部类不能引用外部非静态属性或者方法,非静态内部类不能定义静态属性或者方法),使用外部的属性或者方法,都是从外部成员的类名开始

静态内部类:

public class Outer {

    private int s = 111;
    private static String a="aaa";
    public static class Inner {
        private static String a="aaa";
        private int s = 222;
        public static void mb(int s) {
            System.out.println(s); // 局部变量s
//            System.out.println(this.s); // 内部类对象的属性s,静态内部类不能引用非静态属性或者方法
//            System.out.println(Outer.this.s); // 外部类对象属性s,静态内部类不能引用非静态属性或者方法
            System.out.println(Outer.a);
        }

    }
    public static void main(String args[]) {
//        Outer outer = new Outer();
//       在外部类实例化是时候,内部类并不会实例化,只有在如下需要的时候,才会加载并实例化(此种特性可以应用到对象的懒加载,如果是静态内
//       部类可以实现线程安全
//        Outer.Inner b = a.new Inner();//静态内部类不能实例化
        Outer.Inner.mb(333);
    }
}

非静态内部类

public class Outer {

    private int s = 111;
    private static String a="aaa";
    public class Inner {
//        private static String a="aaa";//非静态内部类不能定义静态属性或者方法
        private int s = 222;
        public void mb(int s) {
            System.out.println(s); // 局部变量s
            System.out.println(this.s); // 内部类对象的属性s,静态内部类不能引用非静态属性或者方法
            System.out.println(Outer.this.s); // 外部类对象属性s,静态内部类不能引用非静态属性或者方法
            System.out.println(Outer.a);
        }

    }
    public static void main(String args[]) {
        Outer outer = new Outer();
 //       在外部类实例化是时候,内部类并不会实例化,只有在如下需要的时候,才会加载并实例化(此种特性可以应用到对象的懒加载,如果是静态内
//       部类可以实现线程安全
        Outer.Inner inner = outer.new Inner();
        inner.mb(333);
    }
}

② 局部内部类
如何使用局部内部类
只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类
但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型

public class AnnoymousInnerClass {
    //返回一个实现了Comparable接口的类的对象
    public Comparable getComparable(){

//        创建一个实现了Comparable接口的类:局部内部类
//        方式一:
		class MyComparable implements Comparable{

			@Override
			public int compareTo(Object o) {
				return 0;
			}
		}
		return new MyComparable();
    }
    
}

二、匿名内部类
个人理解:匿名内部类是局部内部类的特殊形式,就是我们在要使用一个还没有被创建的类的对象的时候,并且只使用一次,为了简便,创建类的同时也创建该类的对象
虽然类没有被创建,但是类所有实现的接口或抽象类我们知道,所以此时以接口名或者抽象类名指代该类,所以叫匿名内部类
看下面的例子(对上面的局部内部类的改造):

public class AnnoymousInnerClass {
    //    返回一个实现了Comparable接口的类的对象
    public Comparable getComparable() {
    //方式二:匿名内部类
        return new Comparable() {
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        };
    }
}

可以看出:匿名内部类实际上也使用了匿名对象

补充:匿名内部类的进一步简化,lambda表达式

public class AnnoymousInnerClass {
    //    返回一个实现了Comparable接口的类的对象
    public Comparable getComparable() {
    //方式二:匿名内部类
        return o -> 0;
    }
}

另外的例子:

public class AnnoymousInnerClass {
    //    返回一个实现了Comparable接口的类的对象
    public Comparable getComparable() {
    //方式二:匿名内部类
        return new Comparable() {
            @Override
            public int compareTo(Object o) {
                System.out.println("lambda表达式");
                return 0;
            }
        };
    }
}
public class AnnoymousInnerClass {
    //    返回一个实现了Comparable接口的类的对象
    public Comparable getComparable() {
    //方式二:匿名内部类
        return o -> {
            System.out.println("lambda表达式");
            return 0;
        };
    }
}

另一个例子:

interface A{
    void  fun1();
}
public class Outer{
    public static void main(String[] args) {
        new Outer().callInner(new A(){
            //接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为对象取名
            @Override
            public void fun1() {
                System.out.println("implement for fun1");
            }
        });// 两步写成一步了
    }
    public void callInner(A a) {
        a.fun1();
    }
}
public class Outer{
    public static void main(String[] args) {
        //接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为对象取名
        new Outer().callInner(
                () -> System.out.println("implement for fun1"));// 两步写成一步了
    }
    public void callInner(A a) {
        a.fun1();
    }
}

实战例子:

   @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
        return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
            @Override
            public void customize(ConfigurableWebServerFactory factory) {
                factory.setPort(8080);
            }
        };
    }
 @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
        return factory -> factory.setPort(8080);
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值