关于static class和public static class的测试记录

事情的起因,在看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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值