`
johnnylzb
  • 浏览: 12797 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类

关于常量类使用的一个问题。

阅读更多
系统有一个常量类,用来保存一些公用的不可变信息,所有常量都被声明为 public static final,但其中一个常量,用于保存系统的绝对路径(WebRoot),这个常量需要在Servlet启动后加载,所以目前就不能把改常量声明为final,但这存在一个非常大的隐患,就是如果某程序员不小心(或恶意)在代码中修改了改常量,将会导致整个系统无法正常运行(因为系统的配置信息文件都保存在该常量指定的路径中)。

这里有两个问题:
1.这种情况,请问有什么比较好的解决方案;

2.对于常量类,他没有公有的构造方法,没有任何静态或非静态方法,只有static成员变量,请问该常量类在内存中会否存在实例,而它的所有成员变量,究竟是在什么时候被实例化到系统的内存当中?是当Web系统被容器加载的时候吗?还是在该常量被第一次调用的时候才延迟加载?
分享到:
评论
12 楼 wjtang 2006-12-28  
同意楼上各位意见,有个建议,对于这一类的信息为什么不用property file or xml file 去保存.
11 楼 shaucle 2006-12-28  
法1 :只读.
private String property1;
<static>{
//load from property files
}
pucblic String getProperty1();
没有set

法2 :只允许设置一次.
void setProperty(){
if(setted){
return or throw
}
//set...
setted = true;
}
10 楼 Readonly 2006-12-28  
johnnylzb 写道
用于保存系统的绝对路径(WebRoot)

题外话,保存系统的WebRoot需要这样做吗?
9 楼 凤舞凰扬 2006-12-28  
johnnylzb 写道
1.这种情况,请问有什么比较好的解决方案;

   这其实和你操作普通的成员变量类似,你可以将静态变量设置为default(也就是不设置)或者privated,然后通过静态方法去get/set值就可以了。一般来说,设置为public的静态变量应该是final的。
johnnylzb 写道

2.对于常量类,他没有公有的构造方法,没有任何静态或非静态方法,只有static成员变量,请问该常量类在内存中会否存在实例,而它的所有成员变量,究竟是在什么时候被实例化到系统的内存当中?是当Web系统被容器加载的时候吗?还是在该常量被第一次调用的时候才延迟加载?

常量类一样有实例,只是这个实例在未使用new之前是不会装载的。VM所做的只是将静态变量和静态方法分配固定的空间。一般说来,静态变量的装载是随着所在类被装载时,这并不是被调用时才装载。比如说有个类Aimport了这个常量类,但是并没有用到其中的方法,那么常量类的静态方法和变量就会被VM装载。这种import可以是具体的,也可以是*,比如import java.util.*。这也是Java编程规范中建议不要使用*的原因之一。
8 楼 johnnylzb 2006-12-27  
非常清楚,谢谢
7 楼 foxty 2006-12-27  
johnnylzb 写道
foxty 写道
johnnylzb 写道
第二个问题?


如果纯粹的只有static属性的话,这个类是不会在系统种存在实例对象的。

它的成员变量如果都是static final的并且在编译时能确定其值,则在编译时便已经将常量写入倒其他引用此属性的类中了。
在编译的时候已经将常量写入到其他引用此属性的类中?

这句话我不大理解,如果其他类是在系统运行的时候才实例化的呢?在这些类都没有实例化的时候,这些常量已经存在于内存当中吗?我还是不清楚这些常量的实例会在什么时候产生的。


举个例子;

class A{
  public static int D = 12;
}

public class B{
  public static void main(String[] args)
  {
    int data = A.D;
    //some operations...
  }
}
这种情况下,classloader载入class B的时候,同时也会载入class A,但是这个时候类A并未初始化(注意不是实例化)。这个时候A.D所指的12是放在class A的常量池中,当程序运行至int data = A.D的时候,才会初始化class A(注意不是实例化),同时查找A的字段列表(从类A的常量池中)获取12。

======================================

class A{
  public static final int D = 12;
}
class B同上。
这种情况下,编译器编译B的时候,发现A.D是一个static而且final的常量,那么它会将这个12直接写入倒class B的字节码当中(即int data = A.D 已经就是int data = 12了),类的载入过程同情况1。

======================================

还有一种特殊情况。
class A{
  public static final int D = new java.util.Random().nextInt();
}
class B同上。
这个时候,编译器编译B的时候虽然发现D是一个static且final的属性,但是它的值确需要在运行时才能确定,所以就无法把D的值嵌入倒B的字节码中,当执行B的mian方法时,还是同第一个情况一样,要去查找A的字段列表获取D。类的载入过程同情况1。
6 楼 LucasLee 2006-12-27  
johnnylzb 写道
系统有一个常量类,用来保存一些公用的不可变信息,所有常量都被声明为 public static final,但其中一个常量,用于保存系统的绝对路径(WebRoot),这个常量需要在Servlet启动后加载,所以目前就不能把改常量声明为final,但这存在一个非常大的隐患,就是如果某程序员不小心(或恶意)在代码中修改了改常量,将会导致整个系统无法正常运行(因为系统的配置信息文件都保存在该常量指定的路径中)。

这里有两个问题:
1.这种情况,请问有什么比较好的解决方案;

2.对于常量类,他没有公有的构造方法,没有任何静态或非静态方法,只有static成员变量,请问该常量类在内存中会否存在实例,而它的所有成员变量,究竟是在什么时候被实例化到系统的内存当中?是当Web系统被容器加载的时候吗?还是在该常量被第一次调用的时候才延迟加载?


这个问题还是比较常见的,有很简单的方法。
1.任何时候你需要控制对变量的访问,你不应该直接暴露这个变量,而是使用getter、setter方法来访问。
  这样你可以将getter方法设置为public,实例变量是private,那么你可以在内部或者其他合适的地方设置此变量值,而其他地方通过getter访问则是只读的。
2.常量变量跟其他变量一样的实例化,不同的只有初始化时能赋值。如果被声明为static的,则是在第一个实例构造之前被创建。
5 楼 codeutil 2006-12-27  
不要用  public static final,这个在编译之后就已经写到其它的class里了,比如
A.class 有  public static final String path="123";
B.class用了它.
然后编译好文件,这个时候修改path为"312",只重新编译A.class,不重新编译B.class,这个时候B.class里的path是不变的.



建议限制为通过get方法访问,且set方法只能够在未初始化的时候执行一次赋值(非null的) 操作.




	private static String path = null;

	public static String getPath() {
		return path;
	}

	public static void setPath(String apath) {
		if (path == null) {
			path = apath;
		}
	}

4 楼 johnnylzb 2006-12-27  
foxty 写道
johnnylzb 写道
第二个问题?


如果纯粹的只有static属性的话,这个类是不会在系统种存在实例对象的。

它的成员变量如果都是static final的并且在编译时能确定其值,则在编译时便已经将常量写入倒其他引用此属性的类中了。
在编译的时候已经将常量写入到其他引用此属性的类中?

这句话我不大理解,如果其他类是在系统运行的时候才实例化的呢?在这些类都没有实例化的时候,这些常量已经存在于内存当中吗?我还是不清楚这些常量的实例会在什么时候产生的。
3 楼 foxty 2006-12-27  
johnnylzb 写道
第二个问题?


如果纯粹的只有static属性的话,这个类是不会在系统种存在实例对象的。

它的成员变量如果都是static final的并且在编译时能确定其值,则在编译时便已经将常量写入倒其他引用此属性的类中了。
2 楼 johnnylzb 2006-12-27  
第二个问题?
1 楼 together 2006-12-27  
常量就应该是final的。
如果需要用到webroot,单独写一个方法去调用好了。request.getRealPath虽然会出现warning,也是能用的。
不然就servlet.getServletContext.getRealPath。系统初始化的时候赋值。

要是怕别人随便改动变量值的话,定期检查代码吧。

相关推荐

    使用类常量方式实现PHP枚举

    在PHP编程中,枚举(Enumeration)是一种常用于定义固定集合中的值的数据类型,它有助于增强代码的可读性和可维护性。...然而,在旧版本的PHP中,使用类常量的模拟方法仍然是一个实用且广泛接受的解决方案。

    C# OFFICE常量类

    C# OFFICE常量类,方便C#操作OFFICE编程。

    C# 定义常量 两种实现方法

    在C#中定义常量的方式有两种,一种叫做静态常量(Compile-time constant),另一种叫做动态常量(Runtime constant)。前者用“const”来定义,后者用“readonly”来定义。 对于静态常量(Compile-time constant),...

    php常量用法类.zip

    主要介绍了php类常量用法,实例分析了php中类常量的概念、特性与相关使用技巧,需要的朋友可以参考下,类常量属于类自身,不属于对象实例,不能通过对象实例访问,子类可以重写父类中的常量,可以通过(parent::)来...

    Windows API常量查询器

    4. **离线使用**:API常量查询器作为一个独立的应用程序,可以在无网络连接的情况下使用,这对于在开发环境中工作或者在无法上网的环境下尤为有用。 5. **更新与同步**:为了保持最新的API常量信息,查询器可能会...

    15353个常量支持库.rar

    例如,“ConstLib.fne”文件可能就是一个包含了各种常用常量的库文件,它使得开发者无需手动创建或记忆这些常量,可以直接调用,提高了代码的可读性和复用性。 常量库的使用有以下几个关键点: 1. **标准化**:...

    变量、常量、类 三方面C#基础的学习资源

    从提供的文件名来看,你可能拥有一个关于C#语言和编程环境的教程系列,特别关注类、常量和变量的讲解。`第3部分 C#语言与编程环境.ppt`可能涵盖了C#的基础环境设置和语言概述,而一系列的`第4部分 类、常量与变量`...

    C#箴言:定义常量的两种方法

    使用`const`定义常量的一个潜在问题是,如果在DLL库中修改了静态常量的值,其他依赖该库的程序可能不会自动更新。因为编译后的中间语言代码已经用旧值替换,这可能导致程序运行时出现不一致的问题。为避免这种问题,...

    apiviewer_gr(常量查询)

    "apiviewer_gr(常量查询)"是一个用于查看和理解编程环境中常量信息的工具。这个工具的主要目的是帮助开发者快速查找和理解代码中使用的常量,提高开发效率和代码质量。常量在编程中扮演着重要的角色,它们通常用来...

    常用的Android常量

    Android的Intent常量是另一个重要的部分。例如,`ACTION_VIEW`表示打开一个视图,`ACTION_CALL`用于拨打电话,`ACTION_SEND`用于分享内容。这些常量在创建意图(Intent)时使用,使代码更加清晰,也方便查阅Android...

    一种基于Spring的java程序常量管理思路

    在Spring中,我们可以创建一个包含常量的配置类,比如`ConstantsConfig`,并使用`@Configuration`注解标识它。然后,我们可以在类中定义`public static final`字段来存储常量,例如: ```java @Configuration ...

    java 常量 变量 详细实例

    1. **final关键字**: 使用`final`关键字可以声明一个常量。例如: ```java final int PI = 3.14; ``` 这里的`PI`就是一个常量,不能被重新赋值。 2. **枚举(Enum)**: 枚举类型可以用来创建一组相关的常量,...

    java 常量与变量

    在上述代码中,`PI`就是一个常量,它的值不能被改变。如果尝试修改常量的值,编译器会抛出错误。 Java还提供了预定义的常量,它们位于`java.lang.Math`类中,如`Math.PI`代表圆周率π。 ### 变量 变量则是可以改变...

    JAVA修改类文件编译不生效

    在 Java 编程中,我们经常会定义一个常量类来管理项目中的常量值,例如: ```java public class AppConst { public static final String STR_CONST_1 = "String1"; public static final String STR_CONST_2 = ...

    易语言API常量查询器1.0

    在使用过程中,"API常量.mdb"文件是查询器的核心数据源,它很可能是一个Microsoft Access数据库文件,包含了所有API常量的详细信息。这种数据库格式可以有效地存储大量数据,并支持快速检索。用户在使用查询器时,...

    API常量查询

    这类工具通常包含一个数据库,包含了大量API常量的定义、值以及相关描述,方便开发者快速查找和理解。使用这样的工具,可以提高编程效率,减少调试时间。 而Const.lyd文件可能是ConstantViewer.exe的配套数据文件,...

    Win32常量查看器

    Win32常量查看器作为一个独立的应用程序,允许开发者通过界面化的形式快速查找和理解Win32 API中的常量。它通常具有以下特性: 1. **搜索功能**:用户可以输入关键词,快速定位到所需常量,节省查找时间。 2. **...

    C#-常量使用-DeclaringConstans

    例如,声明一个整型常量`PI`表示圆周率: ```csharp const double PI = 3.14159; ``` 注意,常量的值必须在声明时就确定,并且是编译时常量。这意味着你不能在运行时改变常量的值,也不能使用表达式来计算其初始值。...

    常量查找工具

    总的来说,"常量查找工具"是一个强大的辅助开发工具,能够帮助程序员快速查找和理解代码中使用的常量,同时提供10进制和16进制之间的转换功能,使得在处理数字表示时更加便捷。"Const.lyd"数据文件和"ConstantViewer...

    易语言源码古木常量查询器.rar

    而古木常量查询器则是这个生态系统中的一个重要辅助工具,它极大地提升了开发者的工作效率。 易语言的常量是预定义的特殊值,开发者在编写代码时可以直接使用,无需自己计算或定义。这些常量涵盖了各种领域,如系统...

Global site tag (gtag.js) - Google Analytics