一、内部类
在内部类中再定义一个类的情况就是内部类, 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);
}
本文详细解析了Java内部类的概念,包括成员内部类和局部内部类的使用场景,以及静态内部类和非静态内部类的区别。同时,介绍了匿名内部类的特性和应用场景,对比了其与局部内部类的差异,最后讲解了Lambda表达式的使用。
572

被折叠的 条评论
为什么被折叠?



