事情的起因,在看spring源码的时候,经常能看到一个内部类,而且,内部类用static关键字修饰。如
@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication @Conditional(SpringBootAdminClientEnabledCondition.class) @AutoConfigureAfter({ WebEndpointAutoConfiguration.class, RestTemplateAutoConfiguration.class, WebClientAutoConfiguration.class }) @EnableConfigurationProperties({ ClientProperties.class, InstanceProperties.class, ServerProperties.class, ManagementServerProperties.class }) public class SpringBootAdminClientAutoConfiguration { @Bean @ConditionalOnMissingBean public StartupDatemetadataContributor startupDatemetadataContributor() { return new StartupDatemetadataContributor(); } @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @AutoConfigureAfter(DispatcherServletAutoConfiguration.class) public static class ServletConfiguration { @Bean @Lazy(false) @ConditionalOnMissingBean public ApplicationFactory applicationFactory(InstanceProperties instance, ManagementServerProperties management, ServerProperties server, ServletContext servletContext, PathMappedEndpoints pathMappedEndpoints, WebEndpointProperties webEndpoint, ObjectProvider> metadataContributors, DispatcherServletPath dispatcherServletPath) { return new ServletApplicationFactory(instance, management, server, servletContext, pathMappedEndpoints, webEndpoint, new CompositemetadataContributor(metadataContributors.getIfAvailable(Collections::emptyList)), dispatcherServletPath); } } @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.REACTIVE) public static class ReactiveConfiguration { @Bean @Lazy(false) @ConditionalOnMissingBean public ApplicationFactory applicationFactory(InstanceProperties instance, ManagementServerProperties management, ServerProperties server, PathMappedEndpoints pathMappedEndpoints, WebEndpointProperties webEndpoint, ObjectProvider
> metadataContributors) { return new DefaultApplicationFactory(instance, management, server, pathMappedEndpoints, webEndpoint, new CompositemetadataContributor(metadataContributors.getIfAvailable(Collections::emptyList))); } } @Configuration(proxyBeanMethods = false) @ConditionalOnBean(RestTemplateBuilder.class) public static class BlockingRegistrationClientConfig { @Bean @ConditionalOnMissingBean public BlockingRegistrationClient registrationClient(ClientProperties client) { RestTemplateBuilder builder = new RestTemplateBuilder().setConnectTimeout(client.getConnectTimeout()) .setReadTimeout(client.getReadTimeout()); if (client.getUsername() != null && client.getPassword() != null) { builder = builder.basicAuthentication(client.getUsername(), client.getPassword()); } return new BlockingRegistrationClient(builder.build()); } } @Configuration(proxyBeanMethods = false) @ConditionalOnBean(WebClient.Builder.class) @ConditionalOnMissingBean(RestTemplateBuilder.class) public static class ReactiveRegistrationClientConfig { @Bean @ConditionalOnMissingBean public ReactiveRegistrationClient registrationClient(ClientProperties client, WebClient.Builder webClient) { if (client.getUsername() != null && client.getPassword() != null) { webClient = webClient.filter(basicAuthentication(client.getUsername(), client.getPassword())); } return new ReactiveRegistrationClient(webClient.build(), client.getReadTimeout()); } } }
为什么要这么写???带着疑问,做了下测试。
package org.test.dog; public class Dog { class A { private String p; public String getP() { return p; } public void setP(String p) { this.p = p; } } static class B { private String p; public String getP() { return p; } public void setP(String p) { this.p = p; } } public class C { private String p; public String getP() { return p; } public void setP(String p) { this.p = p; } } public static class D { private String p; public String getP() { return p; } public void setP(String p) { this.p = p; } } A a = new A(); B b = new B(); C c = new C(); D d = new D(); }
测试的重点,分为两种,一是和 Dog同处一个包里的 InnerPackageTest,目的是为了测试Dog.A, Dog.B,因为它们没有使用public关键字。二是和Dog没有处在同一个包的里的 OutPackageTest。
内部测试类
package org.test.dog; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class InnerPackageTest { private static Integer newline = 2; public static void main(String[] args) throws Exception, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException { Dog a = new Dog(); System.out.println("----------------- A测试开始"); // new Dog.A(); //报错,编译不通过 Dog.A a1 = a.new A(); message("打印实例:", a1); message("构造器个数:", Dog.A.class.getConstructors().length); newline(newline); System.out.println("----------------- B测试开始"); // Dog.B b = new Dog.B(); b.setP(""); message("构造器个数:", Dog.B.class.getConstructors().length); message("打印实例:", b); newline(newline); System.out.println("----------------- C测试开始"); // Dog.C c = a.new C(); message("打印实例:", c); // new Dog.C();// 报错 message("构造器个数:", Dog.C.class.getConstructors().length); Constructor[] cs = Dog.C.class.getConstructors(); for (int i = 0; i < cs.length; i++) { message("构造器的样子:", cs[i].toGenericString()); } Object c2 = Dog.C.class.getConstructors()[0].newInstance(a); message("反射出来的对象", c2.toString()); newline(newline); System.out.println("----------------- D测试开始"); Dog.D d = new Dog.D(); message("打印实例:", d); message("构造器个数:", Dog.D.class.getConstructors().length); cs = Dog.D.class.getConstructors(); for (int i = 0; i < cs.length; i++) { message("构造器的样子:", cs[i].toGenericString()); } Object d2 = Dog.D.class.getConstructors()[0].newInstance(); message("反射出来的对象", d2.toString()); } public static void message(Object... args) { for (int i = 0; i < args.length; i++) { System.out.print(args[i] + "t"); } System.out.println(); } public static void newline(int newline) { for (int i = 1; i <= newline; i++) { System.out.println(); } } }
输出的结果为
----------------- A测试开始 打印实例: org.test.dog.Dog$A@61f8bee4 构造器个数: 0 ----------------- B测试开始 构造器个数: 0 打印实例: org.test.dog.Dog$B@7b49cea0 ----------------- C测试开始 打印实例: org.test.dog.Dog$C@887af79 构造器个数: 1 构造器的样子: public org.test.dog.Dog$C(org.test.dog.Dog) 反射出来的对象 org.test.dog.Dog$C@7fac631b ----------------- D测试开始 打印实例: org.test.dog.Dog$D@5b87ed94 构造器个数: 1 构造器的样子: public org.test.dog.Dog$D() 反射出来的对象 org.test.dog.Dog$D@6e0e048a
外部测试类
package org.test.cat; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.test.dog.Dog; public class OutPackageTest { private static Integer newline = 2; public static void main(String[] args) throws Exception, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException { Dog a = new Dog(); System.out.println("----------------- A测试开始"); // new Dog.A(); //报错,编译不通过 // Dog.A a1 = a.new A();// 报错,编译不通过 // message("打印实例:", a1); // message("构造器个数:", Dog.A.class.getConstructors().length); newline(newline); System.out.println("----------------- B测试开始"); // // Dog.B b = new Dog.B(); //报错,编译不通过 // b.setP(""); // message("构造器个数:", Dog.B.class.getConstructors().length); // message("打印实例:", b); newline(newline); System.out.println("----------------- C测试开始"); // Dog.C c = a.new C(); message("打印实例:", c); // new Dog.C();// 报错 message("构造器个数:", Dog.C.class.getConstructors().length); Constructor[] cs = Dog.C.class.getConstructors(); for (int i = 0; i < cs.length; i++) { message("构造器的样子:", cs[i].toGenericString()); } Object c2 = Dog.C.class.getConstructors()[0].newInstance(a); message("反射出来的对象", c2.toString()); newline(newline); System.out.println("----------------- D测试开始"); Dog.D d = new Dog.D(); message("打印实例:", d); message("构造器个数:", Dog.D.class.getConstructors().length); cs = Dog.D.class.getConstructors(); for (int i = 0; i < cs.length; i++) { message("构造器的样子:", cs[i].toGenericString()); } Object d2 = Dog.D.class.getConstructors()[0].newInstance(); message("反射出来的对象", d2.toString()); } public static void message(Object... args) { for (int i = 0; i < args.length; i++) { System.out.print(args[i] + "t"); } System.out.println(); } public static void newline(int newline) { for (int i = 1; i <= newline; i++) { System.out.println(); } } }
输出的结果为
----------------- A测试开始 ----------------- B测试开始 ----------------- C测试开始 打印实例: org.test.dog.Dog$C@61f8bee4 构造器个数: 1 构造器的样子: public org.test.dog.Dog$C(org.test.dog.Dog) 反射出来的对象 org.test.dog.Dog$C@7b49cea0 ----------------- D测试开始 打印实例: org.test.dog.Dog$D@887af79 构造器个数: 1 构造器的样子: public org.test.dog.Dog$D() 反射出来的对象 org.test.dog.Dog$D@7fac631b
总结一下,学习到的内容。
1、内部类A,B,由于没有使用修饰符,则默认的范围为包级别,这一点不变。
2、内部类A,B,在同一个包里被引用的时候,不能直接new,而是要通过Dog的实例对象来new。通过获取到的构造器个数来看,数量为0,也证实了这一点。
3、内部类C,如果只加了public,而不是public static时,根据获取的造造器来看,是有一个Dog参数的,所以,内部类C,虽然有public关键字,也是不能直接new。
4、内部类D,是通过public static 关键字来修饰的,进一步观察构造器,和普通的类(一个文件一个类,且是public级的)没有任何区别,所以,能够在包外直接new。
5、不能用static修饰顶级类Dog,只有内部类可以为static。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)