Java Interface是存放常量的最好地方吗?(转)
虽然Inteface中默认常量就是static final 的。因此很多人就认为其实存放常量的最佳地方,effective java中就提过,不建议使用常量接口。其有一个原因就是:代码编译问题
好,我们来看一个简单的例子:
有一个interface A,一个class B,代码如下:
//file A.java
public interface A{
String name = "bright";
}
//file B.java
public class B{
public static void main(String[] args){
System.out.println("Class A's name = " + A.name);
}
}
够简单吧,好,编译A.java和B.java。
运行,输入java B,显然结果如下:
Class A's name = bright
我们现在修改A.java如下:
//file A.java
public interface A{
String name = "bright sea";
}
编译A.java后重新运行B class,输入java B,注意:结果如下
Class A's name = bright
为什么不是"Class A's name = bright sea"?让我们使用jdk提供的反编译工具javap反编译B.class看个究竟,输入:javap -c B ,结果如下:
Compiled from B.java
public class B extends java.lang.Object {
public B();
public static void main(java.lang.String[]);
}
Method B()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 return
Method void main(java.lang.String[])
0 getstatic #2 <Field java.io.PrintStream out>
3 ldc #3 <String "Class A's name = bright">
5 invokevirtual #4 <Method void println(java.lang.String)>
8 return
注意到标号3的代码了吗?由于引用了一个static final 的字段,编译器已经将interface A中name的内容编译进了class B中,而不是对interface A中的name的引用。因此除非我们重新编译class B,interface A中name发生的变化无法在class B中反映。如果这样去做那么java的动态优势就消失殆尽。
解决方案,有两种解决方法。
第一种方法是不再使用常量,将所需字段放入class中声明,并去掉final修饰符。但这种方法存在一定的风险,由于不再是常量着因而在系统运行时有可能被其他类修改其值而发生错误,也就违背了我们设置它为常量的初衷,因而不推荐使用。
第二种方法,将常量放入class中声明,使用class方法来得到此常量的值。为了保持对此常量引用的简单性,我们可以使用一个静态方法。我们将A.java和B.java修改如下:
//file A.java
public class A{
private static final String name = "bright";
public static String getName(){
return name;
}
}
//file B.java
public class B{
public static void main(String[] args){
System.out.println("Class A's name = " + A.getName());
}
}
同样我们编译A.java和B.java。运行class B,输入java B,显然结果如下:
Class A's name = bright
现在我们修改A.java如下:
//file A.java
public class A{
private static final String name = "bright";
public static String getName(){
return name;
}
}
我们再次编译A.java后重新运行B class,输入java B:结果如下
Class A's name = bright sea
终于得到了我们想要的结果,我们可以再次反编译B.class看看class B的改变,输入:
javap -c B,结果如下:
Compiled from B.java
public class B extends java.lang.Object {
public B();
public static void main(java.lang.String[]);
}
Method B()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 return
Method void main(java.lang.String[])
0 getstatic #2 <Field java.io.PrintStream out>
3 new #3 <Class java.lang.StringBuffer>
6 dup
7 invokespecial #4 <Method java.lang.StringBuffer()>
10 ldc #5 <String "Class A's name = ">
12 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)>
15 invokestatic #7 <Method java.lang.String getName()>
18 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)>
21 invokevirtual #8 <Method java.lang.String toString()>
24 invokevirtual #9 <Method void println(java.lang.String)>
27 return
注意标号10至15行的代码,class B中已经变为对A class的getName()方法的引用,当常量name的值改变时我们只需对class A中的常量做修改并重新编译,无需编译整个项目工程我们就能改变整个应用对此常量的引用,即保持了java动态优势又保持了我们使用常量的初衷,因而方法二是一个最佳解决方案。
Java Interface是存放常量的最好地方吗?(转)的更多相关文章
- Java Interface 是常量存放的最佳地点吗?(转帖学习,非原创)
Java Interface 是常量存放的最佳地点吗?(转帖学习,非原创) 由于java interface中声明的字段在编译时会自动加上static final的修饰符,即声明为常量.因而inter ...
- JAVA基础——变量和常量
JAVA的变量和常量知识总结 一.认识java标识符 标识符就是用于给 Java 程序中变量.类.方法等命名的符号. 使用标识符时,需要遵守几条规则: 1. 标识符可以由字母.数字.下划线(_).美 ...
- JAVA 基础基本语法---常量与变量
JAVA 基础基本语法---常量与变量 语法:计算机能够识别的语言的规则: 0. 基本语法 编写Java程序时,应注意以下几点: 大小写敏感:Java是大小写敏感的,这就意味着标识符Hello与hel ...
- Java学习笔记三:Java的变量、常量、变量的类型及使用规则
Java的变量.常量.变量的类型及使用规则 每一种语言都有一些具有特殊用途的词,Java也不例外,它们被称为关键字.关键字对 Java 的编译器有着特殊的意义. 一:Java中的关键字: 注:Java ...
- Java基础二:常量池
目录: 自动装箱与拆箱 常量池 ==与equals()区别 1. 自动装箱与拆箱 Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成 ...
- 转载:Java中的字符串常量池详细介绍
引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重 ...
- Java提高篇之常量池
一.相关概念 1. 什么是常量 用final修饰的成员变量表示常量,值一旦给定就无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. 2. Class文件中的 ...
- Java复习3.变量.常量.String.
Java 中的变量常量数据类型 20131004 前言: 还是国庆节,无聊的很,就没事复习点Java的知识,其实C/C++基本上是现在大型企业面试的语言,但是多学习点Java是没有坏处的,而且,将来工 ...
- Java中的字符串常量池,栈和堆的概念
问题:String str = new String(“abc”),“abc”在内存中是怎么分配的? 答案是:堆内存.(Tips:jdk1.8 已经将字符串常量池放在堆内存区) 题目考查的为Ja ...
随机推荐
- ABAP写的一个递归
需求:计算下面树形结构中每个子节点与最上层父节点的对应关系. DATA:BEGIN OF lt_ztab OCCURS 0, a TYPE string, b TYPE str ...
- uva 12526 - Cellphone Typing
字典树,可惜比赛的时候有两句话写倒了: 害得我调了一个小时: 今天不宜做题 = = 代码: #include<cstdio> #include<cstring> #define ...
- 养成一个SQL好习惯带来一笔大财富
我们做软件开发的,大部分人都离不开跟数据库打交道,特别是erp开发的,跟数据库打交道更是频繁,存储过程动不动就是上千行,如果数据量大,人员 流动大,那么我么还能保证下一段时间系统还能流畅的运行吗?那么 ...
- POJ 2409 Let it Bead(Polya定理)
点我看题目 题意 :给你c种颜色的n个珠子,问你可以组成多少种形式. 思路 :polya定理的应用,与1286差不多一样,代码一改就可以交....POJ 1286题解 #include <std ...
- Android 使用XmlSerializer生成xml文件
在Android开发中,我们时常要用到xml文件. xml作为一种数据载体,在数据传输中发挥着重要的作用,而且它可读性比较强. 下面给出在Android开发中使用XmlSerializer类生成一个简 ...
- iOS开发UI篇—UITableviewcell的性能问题
iOS开发UI篇—UITableviewcell的性能问题 一.UITableviewcell的一些介绍 UITableView的每一行都是一个UITableViewCell,通过dataSource ...
- OA学习笔记-007-Dao层设计
一. User, UserDao save(User user), update(), delete(), find(), ...Role, RoleDao save(Role role), upda ...
- statspack系列5
原文:http://jonathanlewis.wordpress.com/2006/12/27/analysing-statspack-5/ 作者:Jonathan Lewis 前些天,有人给我发了 ...
- 读完了简明Python教程(a bite of Python)
因为学过C/C++,简明教程里很多共通的地方一看就明白. 明天做书最后的练习. <--! 代码占位 -->
- Delphi的BPL介绍和使用 转
了解BPL和DLL的关系将有助于我们更好地理解DELPHI在构件制作.运用和动态.静态编译的工作方式.对初学DELPHI但仍对DELPHI开发不甚清晰的朋友有一定帮助.BPL vs. DLL(原文ht ...