irpas技术客

关于static class和public static class的测试记录_程序人生

irpas 6454

事情的起因,在看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<List<MetadataContributor>> 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<List<MetadataContributor>> 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; /** * 演示了内部测试(InnerPackageTest和Dog所处同一个包)。 * * @author cpp * */ 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; /** * 演示了外部测试(OutPackageTest和Dog,没有在同一个包内)。 * * @author cpp * */ 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。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #关于static #class和public #static #class的测试记录