Author: my name is Liu Banxian my.oschina.net/liughDevelop/blog/1490005
Static variables and methods are used in many applications, but there are many problems when they are used. Static variables and methods are used in many applications.
Static variables.
2. Static methods.
3. Static code blocks.
Static inner classes.
5. Static import.
Let’s take a look at these uses.
Static variables
A static variable is a class that has only one instance in memory. When the class is loaded, it is allocated memory and stored in the method area alongside the class itself, never to be reclaimed unless the JVM exits. Static variables can be used in the following ways: class name. Variable name and object. Variable name.
The dateFormat class SimpleDateFormat will be used a lot. If necessary, we will create a new object and use it directly. But we know that creating objects frequently is not good, so we will create a static SimpleDateFormat global variable in DateUtil. Using this instance directly saves performance because of memory sharing. However, it has thread safety problems under high concurrency. SimpleDateFormat Thread safety problem
public class OuterStatic { public static class InnerStaticSimpleDateFormat implements Runnable { @Override public void run() { while(true) { try { Thread.sleep(3000); System.out.println(Thread.currentThread().getName() +":"+DateUtil.parse("2017-07-27 08:02:20")); } catch (Exception e) { e.printStackTrace(); } } } } public static void main(String[] args) { for(int i = 0; i < 3; I++) {new Thread (new InnerStaticSimpleDateFormat (), "test Thread"). The start (); } } } class DateUtil { private static volatile SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static String formatFromDate(Date date)throws ParseException{ return sdf.format(date); } public static Date parseToDate(String strDate) throws ParseException{ return sdf.parse(strDate); }}Copy the code
Although there is a volatile object is visible, but after running a certain risk to Java. Lang. A NumberFormatException: multiple points or For input string: (SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat: SimpleDateFormat
Solutions:
-
Use private objects.
-
Lock. Recommended: Java virtual machine lock optimization efforts
-
ThreadLocal. Recommended: Multithreaded concurrency artifact –ThreadLocal
-
Use a third-party date handler.
-
5.Java8 introduced thread-safe, simple, highly reliable time package, which has LocalDateTime year month day 10 minutes and seconds; LocalDate date; Three classes LocalTime time are available. Recommended: New feature extensions for JDK8
The following diagram illustrates the use of private objects and ThreadLocal to address high concurrency.
This article gives the use of private objects and locking two implementation code, ThreadLocal readers can try their own implementation
public class DateUtil { private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Public static String formatFromDate(Date Date)throws ParseException{// SDF = new SimpleDateFormat(" YYYY-MM-DD HH: MM :ss"); //SimpleDateFormat SDF = new SimpleDateFormat(" YYYY-MM-DD HH: MM :ss"); //return sdf.format(date); Synchronized (SDF){return sdf.format(date); synchronized(SDF){return SDF. }} public static Date parseToDate(String strDate) throws ParseException{// Method 1: Comment out the global variable SDF //SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //return sdf.parse(strDate); Synchronized (SDF){return sdf.parse(strDate); synchronized(SDF){return sdf.parse(strDate); }}}Copy the code
# # #
2. Static methods
Static and non-static methods, like the class itself, are stored in memory and are never reclaimed unless the JVM exits. One of the differences they use is that non-static methods need to be called by the instance, whereas static methods are called directly by the class name. Reply keyword: _Java_ in the background of wechat official account of Java technology stack, you can get more Java technology dry goods with stack length sorted. Recommended: Interface default and static methods for new JDK8 features.
Singleton pattern, which provides the best way to create objects, ensures that there is only one instance of a class, and provides a global access point to it.
public class Singleton { private static volatile Singleton instance = null; Instance = new Singleton(); instance = new Singleton(); } private Singleton (){} public static Singleton getInstance() { return instance; }}Copy the code
Static method does not need to instantiate can be directly used, convenient usage, do not frequently open up space for objects and objects are recycled, saving system resources. Is static more pleasant? But it also brings some problems:
Static order export (); static order export ();
public class ExportExcelUtil{ @Autowired private static OrderService orderService ; Public static void exportExcel(String id){// Query the data of the Order to export Order Order =orderService.getById(id); // Here orderService object will be null //... Omit export code... }}Copy the code
Why is orderService null? The reason is not that Spring does not inject, but that static methods “empty” it. Solution 1: @postConstruct, which decorates methods that are executed once when the Servlet is loaded by the server, looks like this:
Public class ExportExcelUtil{@autoWired OrderService OrderService; private static ExportExcelUtil exportExcelUtil; PostConstruct is a block of code that states that when you load the constructor of a class, you copy the service to a static service. @PostConstruct public void init() { exportExcelUtil= this; exportExcelUtil.orderService = this.orderService ; } public static void exportExcel(String id){public static void exportExcel(String id){ Order order =exportExcelUtil.orderService .getById(id); / /... Omit export code... }}Copy the code
Every utility class has to be annotated with @postConstruct, which makes code repeatable. Can we get the Bean instance directly from the Spring container?
Solution 2: ApplicationContextAware. The Spring container automatically injects context objects into the setApplicationContext method in the implementation class of the ApplicationContextAware interface. Recommended: Spring Aware container awareness technology
In other words, we can get beans in the Spring container from this context object in the implementation class of ApplicationContextAware.
First, configure the Listener to load the Spring container in web.xml in your Web project:
<! Initialize the Spring container, Let the Spring container start automatically when the Web application starts --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>Copy the code
Then, implement the ApplicationContextAware interface:
public class SpringContextBean implements ApplicationContextAware{ private static ApplicationContext context = null; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext; } public static <T> T getBean(String name){ return (T)context.getBean(name); } public static <T> T getBean(Class<T> beanClass){ return context.getBean(beanClass); }}Copy the code
Finally, register the utility class in the Spring configuration file:
<bean id="springContextBean" class="com.test.SpringContextBean"></bean>Copy the code
The original export utility class code can be simplified as follows:
public class ExportExcelUtil{ public static void exportExcel(String id){ OrderService orderService = SpringContextBean.getBean(OrderService.class); Order order =orderService .getById(id); / /... Omit export code... }}Copy the code
# # #
3. Static code blocks
We actually use code blocks all the time in our work. A code block is a piece of code surrounded by {}. Where the static code block is executed only once, the construction code block is executed each time the object is created. Code blocks can be divided into four types according to their location: normal code blocks, construction blocks, static code blocks, and synchronous code blocks. Ref: Common code blocks in Java, constructed code blocks, static code block differences and code examples. Reply keyword: _Java_ in the background of wechat official account of Java technology stack, you can get more Java technology dry goods with stack length sorted. Recommended: Interface default and static methods for new JDK8 features
Because the JVM only allocates memory statically once, memory allocation for static variables is done during class loading. So in practice we can use static code blocks to initialize some immutable properties:
Public static final map <String,String> spuKeysMap = new HashMap<String,String>(); Static {spuKeysMap. Put ("spuName"," men "); static{spuKeysMap. SpuKeysMap. Put ("spuCode"," men's code "); SpuKeysMap. Put (" spuBrand ", "brand"); SpuKeysMap. Put ("owner"," owner"); spuKeysMap. }Copy the code
But what does a static code block have to do with static variable initialization? In the singleton pattern above, we used static blocks of code to create objects. Why did we write that way? I saw this code on the Internet:
static {
_i = 10;
}
public static int _i = 20;
public static void main(String[] args) {
System.out.println(_i);
}Copy the code
Is the result 10 or 20? What if there are multiple code blocks?
static {
_i = 10;
} public static int _i =30; static {
_i = 20;
}
public static void main(String[] args) {
ystem.out.println(_i);
}Copy the code
And then you’ll see that both answers are 20.
Public static int I = 10; And the following code:
public static int _i;
static {
_i = 10;
}Copy the code
There is no difference, their compiled bytecode is exactly the same (the reader can view the bytecode file using the javap -c command), so the result of both examples is the value of the last assignment.
Static inner classes
An inner class becomes a static inner class when you define it with the permission modifier static. Reply keyword: _Java_ in the background of wechat official account of Java technology stack, you can get more Java technology dry goods with stack length sorted.
Instantiate (getInstance, getInstance, getInstance, getInstance, getInstance, getInstance, getInstance, getInstance, getInstance, getInstance); Due to the poor performance of hankhan writing method, the final singleton mode was optimized as follows:
Private static class SingletonHolder{private static volatile Singleton instance = new Singleton(); } private Singleton (){} public static Singleton getInstance() { return SingletonHolder.instance; } public static void otherMothed(){system.out.println (" The object is not created when other methods of the singleton are called.")} public static void main(String [] args){ //Singleton.otherMothed(); Singleton.getInstance(); }}Copy the code
There is not much use of the inner class for bloggers in practical development, but sometimes it is necessary to do without it. For example, LinkedList uses the following static inner class:
In fact, we refer to next and prev as Pointers to the front and back nodes in the data structure, and the static array of internal class Entry is also used to store data in HashMap. To understand this, you can run the following code to experience static inner classes for yourself.
Private static String name = "private static String name "; Public static void main(String[] args) {new static internal ().outmethod (); } public static void outStaticMethod(String tempName) {system.out.println (" +tempName "); } public void outMethod() {// The outer class accesses the static member of the static inner class: the inner class. Static member System.out.println(" non-static method calls from external classes "); StaticInternal.InnerStaticClass inner = new StaticInternal.InnerStaticClass(); // Instantiate the static inner class object inner. SetInnerName (" whoo "); / / access non-static methods of the static inner class. InnerStaticClass innerStaticMethod (); System.out.println(" inner class calls inner class non-static method name:"+inner.getinnerName ()); } static class InnerStaticClass {String InnerName=" InnerStaticClass "; Static void innerStaticMethod() {system.out.println (" name = "+ name); static void innerStaticMethod() {system.out.println (" name =" + name); outStaticMethod(new InnerStaticClass().InnerName); Public void setInnerName(String name) {system.out.println (" static inner class non-static method "); this.InnerName = name; } public String getInnerName() {system.out.println (" static inner class get method name="+name); return this.InnerName; }}Copy the code
The SpringMvc static inner class encapsulates the request data. Here we summarize the static inner class:
1. Improve code readability. Such as: StaticInternal InnerStaticClass inner = new StaticInternal. InnerStaticClass ();
2. Objects of multiple external classes can share objects of the same static inner class.
3. A static inner class does not need to depend on an external class; it can exist independently of an external object. Because static classes and methods belong only to the class itself, they do not belong to the objects of that class, much less to the objects of other external classes.
5. Static import
Static import is a new feature added after JKD1.5. It is not commonly used. Sometimes this can come out of an interview and make other people think you love technology.
Recall that we used to write random numbers like this:
public static void main(String[] args) { double random = Math.random();
System.out.println(Math.PI);
System.out.println(Math.round(random));
}Copy the code
Math comes up too often. Can it be simplified? Now we can write directly using static imports as follows
import static java.lang.Math.*;public class StaticInternal {
public static void main(String[] args) { double random = random();
System.out.println(PI);
System.out.println(round(random));
}
}Copy the code
Is it much more convenient? Don’t be lazy, though, because using it too much can lead to code readability:
import static java.lang.Math.*; import static java.lang.Integer.*; public class StaticInternal { public static void main(String[] args) { double random = random(); System.out.println(PI); System.out.println(round(random)); System.out.println(bitCount(11)); }}Copy the code
You probably know that PI is a method of the Math class, but which class is bitCount? So try to avoid using the static imports, really want to import, remove the * wildcard, direct written: Java. Lang. Integer. BitCount.
Follow the wechat official account of Java technology stack and reply the keyword _Java_ in the background to get more Java technology dry goods with stack length sorted.
Read more on my blog:
1.Java JVM, Collections, Multithreading, new features series tutorials
2.Spring MVC, Spring Boot, Spring Cloud series tutorials
3.Maven, Git, Eclipse, Intellij IDEA series tools tutorial
4.Java, backend, architecture, Alibaba and other big factory latest interview questions
Life is good. See you tomorrow