A deep understanding of the role of final in Java (1): analyzes the deep reasons why String is designed as an immutable class from the role of final

Source: Internet
Author: User

Disclaimer: this blog is an original blog and cannot be reproduced without permission! If you see it in other places, it is recommended to take a look at csdn (the original link for the http://blog.csdn.net/bettarwang/article/details/26744661), read the code and ask questions, discussion is more convenient.

In Java, final is mainly used in three aspects: Variable modification, modification method and modification class. The role of final is explained in the following two aspects. At the end of the article, starting from the design security of final and classes, it discusses why the String in Java is designed as an immutable class.

1. final modifier variable

The final modifier is similar to the const in C ++. If it is a basic type variable, the value cannot be changed. If it is a reference type variable, it indicates that it is initialized, you can no longer point to other objects, but note that the value of the object to which it points can be changed (in fact, this is also similar to the common pointer in C ++ ). Let's see the following example.

Import java. util. *; class Apple {private float weight; public Apple (float weight) {setWeight (weight);} public void setWeight (float weight) {this. weight = weight;} public void print () {System. out. println ("Weight is" + String. valueOf (weight);} public void printHashCode () {System. out. println ("HashCode:" + String. valueOf (hashCode ();} public class FinalSample {public static void main (String [] args) {Final int a = 10; // The final modified basic type variables cannot be modified once initialized. // a = 20; final Apple = new apple (300f ); apple. print (); apple. printHashCode (); // The reference type variable modified by final cannot be changed, but the object to which it points can be changed. Apple. setWeight (350f); apple. print (); apple. printHashCode ();}}

Shows the output result:


Obviously, the final-modified basic type variable a cannot be changed. The output hash code remains unchanged and apple always points to the same object, however, weight, a member of the object to which it points, has changed.

It is precisely because the final variable of the reference type "can only point to unchanged, but cannot ensure that the object itself to be pointed to remains unchanged", so be especially careful when constructing the class, otherwise it is easy to be used by hackers. Let's see the following example.

import java.util.*;class AppleTag{  private float weight;  private float size;  public AppleTag(float weight,float size)  {    setWeight(weight);    setSize(size);  }  public void setWeight(float weight)  {    this.weight=weight;  }  public float getWeight()  {    return weight;   }  public void setSize(float size)  {    this.size=size;  }  public float getSize()  {    return size;  }}public class Apple{  private final AppleTag appleTag;  public Apple(AppleTag appleTag)  {    this.appleTag=appleTag;  }  public AppleTag getAppleTag()  {    return appleTag;  }  public void print()  {    System.out.println("Weight:"+String.valueOf(appleTag.getWeight())+                            " Size:"+String.valueOf(appleTag.getSize()));  }     public static void main(String[]args)  {    AppleTag appleTag=new AppleTag(300f,10.3f);    Apple apple=new Apple(appleTag);    apple.print();       appleTag.setWeight(13000f);    apple.print();       AppleTag tag=apple.getAppleTag();    tag.setSize(100.3f);    apple.print();  }}
Shows the output result:


The designer of the class is intended to prevent the appleTag from being modified once initialized, and deliberately does not provide the set function to prevent it from being tampered. However, in fact, the user of the class can modify the appleTag from two places to change apple. One is to use the real parameters in the constructor to modify, and the other is to use getAppleTag () the Return Value of the function is modified.

Obviously, this example releases excessive permissions due to improper class design, so that the class user can modify the apple weight and size to a very unreasonable value to get the wrong result. So how should we avoid such errors?

The Code is as follows:

import java.util.*;class AppleTag{  private float weight;  private float size;  public AppleTag(float weight,float size)  {    setWeight(weight);    setSize(size);  }  public void setWeight(float weight)  {    this.weight=weight;  }  public float getWeight()  {    return weight;   }  public void setSize(float size)  {    this.size=size;  }  public float getSize()  {    return size;  }}public class Apple{  private final AppleTag appleTag;  public Apple(AppleTag appleTag)  {    this.appleTag=new AppleTag(appleTag.getWeight(),appleTag.getSize());  }  public AppleTag getAppleTag()  {    return new AppleTag(appleTag.getWeight(),appleTag.getSize());  }  public void print()  {    System.out.println("Weight:"+String.valueOf(appleTag.getWeight())+                            " Size:"+String.valueOf(appleTag.getSize()));  }     public static void main(String[]args)  {    AppleTag appleTag=new AppleTag(300f,10.3f);    Apple apple=new Apple(appleTag);    apple.print();       appleTag.setWeight(13000f);    apple.print();       AppleTag tag=apple.getAppleTag();    tag.setSize(100.3f);    apple.print();  }}
The program output result is as follows:


Apparently, although the user of the class still tries to modify the appleTag beyond the authority, it fails to succeed because: During receiving, an object is created inside the class and the appleTag points to it; in the output, the user obtains the new object, ensuring that the user can obtain the corresponding value, and cannot use the obtained object to modify the appleTag. Therefore, apple has never changed, and the three outputs are the same.

In my blog "deep understanding of the differences between String, StringBuffer, and StringBuilder in Java", I have already said that the String object is immutable, therefore, when using String, you do not have to worry about tampering with objects even if you directly return a reference, as shown in the following example:

import java.util.*;class Apple{  final String type;  public Apple(String type)  {    this.type=type;  }  public String getType()  {    return type;   }  public void print()  {    System.out.println("Type is "+type);   }}public class AppleTest{  public static void main(String[]args)  {    String appleType=new String("Red Apple");    Apple apple=new Apple(appleType);    apple.print();    appleType="Green Apple";    apple.print();    String type=apple.getType();    type="Yellow Apple";    apple.print();  }}    
The output result is as follows:

Programming languages, strings, and their processing all account for a large proportion), which will obviously cause great inconvenience to our daily programming.

Another note is that the array variable name is actually a reference, so when final modifies the array, the array members can still be changed.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.