请教几个概念方面的问题,弄懂马上揭贴!

jsjwql 2003-08-29 08:41:35
1,今天看了程序员蔡学镛专栏,有一个疑问就是,“……上述的instancemethod1()内部可以出现instancefiled。如果某class的class method或instance method 欲使用到某instance的instance field,就必须在前面冠上instance名称,例如obj.classfield”//对于instance field不是不能被class method访问吗?

2,对于instance field可以在constructor中初始化,class field可以通过static initializer中进行。一个class如果没有定义constructor,那么编译器回制造一个default constructor给你。static initializer是一个类似constructor的method,称为staticnitializer,它是通过
static{
//……
}
来执行的。

//我想问的就是就我所知道的在类中很少有看到staticnitializer的方法,是不是想constructor一样编译器会生成一个默认的,如果有是什么样的?

再就是,constructor与staticnitializer都是用于初始化的,但是constructor是在生成对象的时候才执行的,那staticnitializer是什么时候执行的,我对“类加载的时候”不是很理解?

如果我既有constructor也有直接用int a=3类似的方法进行了初始化,都是进行初始话,那在建立对象的时候先执行哪个初始话呢?



...全文
48 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
jsjwql 2003-08-31
  • 打赏
  • 举报
回复
终于弄明白了 ,谢谢兄弟了
现在唯一的遗憾就是不能多给你点分!呵呵
这样吧,你到我的另外的一个问题去看看,等你去拿分!
http://expert.csdn.net/Expert/topic/2204/2204247.xml?temp=.2414209
jsjwql 2003-08-30
  • 打赏
  • 举报
回复
上面的列子看的不太懂!
zhh200308 2003-08-30
  • 打赏
  • 举报
回复
看来还得打打字,不然没分挣了,呵呵:)

蔡学镛的文章我没看过,我先按我的理解来解说一下:
instance filed: 实例变量或者说实例字段
简单说就是一个类中不带static的变量(普通的成员变量);

instance method:实例方法
简单说就是一个类中不带static的方法;

class filed:类变量或者说类字段,静态成员变量都可以
简单说就是一个类中带static的变量,类变量只属于当前类,而不属于当前类的具体的某个实例。
比如说上面那个例子中的"nextId"就是一个类变量,它只属于Employee类,而不是由
Employee类的实例staff[0]、staff[0]、staff[0]来管,初始化只在类首次被加载时进行,
拿Employee类来说,nextId的值只在staff[0] = new Employee("Harry", 40000);
时进行初始化,随机得到一个小于10000的整数,在进行staff[1] = new Employee(60000);
staff[2] = new Employee();时都不会再进行初始化了;而"id"则是属于实例变量,每次在
进行new Employee()时都初始化一次。
总之一句话每个实例变量有多个拷备(可以想象在内存中用多个不同的地址来存放数据),
分别属于当前类的不同实例,
而类变量只有一个拷备(可以想象在内存只有一个地址来存放类变量的数据),
所有的实例共享一个类变量.

class method:类方法
简单说就是一个类中带static的方法,类方法只属于当前类,而不属于当前类的具体的某个实例。
main()就是一个类方法,类方法只能防问该类的类变量或者该类其他的类方法,而不能防问该类的
实例方法和实例变量。

下面解释一下他的原话:
<<"上述的instancemethod1()内部可以出现instancefiled。"
实例方法内部可以出现实例变量,这当然可以了。

<<"如果某class的class method或instance method 欲使用到某instance的instance
<<field,就必须在前面冠上instance名称,例如obj.classfield"
如果某个类的类方法或实例方法要用到另一个实例的实例变量,必须在前面加上实例名称.

如果光按字面理解的话不完全正确,只有当前实例的实例变量为public或者当前实例所属类
和使用该实例的类是在同一个包(package),而且当前实例的实例变量不是private时才是
正确的,否则编译时很难通过。
给几个例子你可以试一下:

正确的情况:
a.不同包,但C2类的实例变量i为public:
目录结构:
D:\test\A\C1.java;
D:\test\B\C2.java;

package A;
import B.C2;
class C1
{
public static void main(String[] args)
{
C2 c2=new C2();
c2.print();
System.out.println("C2.i="+c2.i);
}
}

package B;
public class C2
{
public int i=1;
public void print() {
System.out.println("call C2.print()");
}
}


b.相同包,C2类的实例变量i为默认级别(相同包可见):
目录结构:
D:\test\A\C1.java;
D:\test\A\C2.java;

package A;
class C1
{
public static void main(String[] args)
{
C2 c2=new C2();
c2.print();
System.out.println("C2.i="+c2.i);
}
}

package A;
public class C2
{
int i=1;
public void print() {
System.out.println("call C2.print()");
}
}

错误情况:
b.相同包,C2类的实例变量i为private:
目录结构:
D:\test\A\C1.java;
D:\test\A\C2.java;

package A;
class C1
{
public static void main(String[] args)
{
C2 c2=new C2();
c2.print();
System.out.println("C2.i="+c2.i);
}
}

package A;
public class C2
{
private int i=1;
public void print() {
System.out.println("call C2.print()");
}
}

其实采用这种方法完全不符合OO的思想,破坏了卦装,
应该采用getXXX()来访问实例变量。

<<"//对于instance field不是不能被class method访问吗?"
蔡学镛的意思是说"欲使用到某instance的instancefield"也就是
要用别的实例的实例变量,而不是你所想的用class method所属类的
实例变量,就像上面例子中的System.out.println("C2.i="+c2.i);
完全可以的。


<<2,我想问的就是就我所知道的在类中很少有看到staticnitializer的方法,
<<是不是想constructor一样编译器会生成一个默认的,如果有是什么样的?
在我给的Employee例子中
static
{
Random generator = new Random();
System.out.println("9");
// set nextId to a random number between 0 and 9999
nextId = generator.nextInt(10000);
}
就是一个staticnitializer了(静态成员变量快,只能用来初始静态成员变量)
作用就是为静态成员变量赋初始值带来很大的灵活性,就像上面一样,如果nextId
的初始值要经过很多逻辑才能得到,比如说先要产生一个随机数,然后再求平方,
最后又要做其他乱七八糟的东西,如果单单一个赋值语句是很难搞定的,
staticnitializer主要就是带来这方面的好处,不过程序的可读性就比较差了.

如果程序里没有static块,或者在static块中没有为所有的静态成员变量赋初始值,
你必须在申明该静态成员变量的地方为它赋初始值,如果你没有为它赋值的话,在类
第一次被实例化时,会默认的为它赋初始值,比如说int型的会得到一个0值,
String型的会是null,boolean的为false.

至于编译器会不会产生一个默认的静态成员变量初始方法,这个我不懂,你可以去问问
sun公司,得到答案后还请发短消息给我哦,不要再告诉第三者哦,呵呵。。。

好了就写这么多了(手好累:)
希望能有一点帮助了,如还不清楚,多看点书了。。。
jsjwql 2003-08-30
  • 打赏
  • 举报
回复

zhh200308(虚荣心与星星) :
我看我这分可以被你包了,呵呵
你帮我回答以下:
1,今天看了程序员蔡学镛专栏,有一个疑问就是,“……上述的instancemethod1()内部可以出现instancefiled。如果某class的class method或instance method 欲使用到某instance的instance field,就必须在前面冠上instance名称,例如obj.classfield”//对于instance field不是不能被class method访问吗?
2,我想问的就是就我所知道的在类中很少有看到staticnitializer的方法,是不是想constructor一样编译器会生成一个默认的,如果有是什么样的?
zhh200308 2003-08-30
  • 打赏
  • 举报
回复
去书店找找<<最新java2核心技术 卷I:原理(原书第5版)>>,
从第124页看到131页,看完后你就很清楚了,除非。。。

这些东西很基础了,懒得打字了,呵呵,别拿砖头砸我。。。
zhh200308 2003-08-29
  • 打赏
  • 举报
回复
给你个例子参考吧,能说明很多问题(core java 1上的例子)

/**
@version 1.00 2000-01-27
@author Cay Horstmann
*/

import java.util.*;

public class ConstructorTest
{
public static void main(String[] args)
{
// fill the staff array with three Employee objects
Employee[] staff = new Employee[3];

staff[0] = new Employee("Harry", 40000);
staff[1] = new Employee(60000);
staff[2] = new Employee();

// print out information about all Employee objects
for (int i = 0; i < staff.length; i++)
{
Employee e = staff[i];
System.out.println("name=" + e.getName()
+ ",id=" + e.getId()
+ ",salary=" + e.getSalary());
}
}
}

class Employee
{
// three overloaded constructors
public Employee(String n, double s)
{
name = n;
salary = s;
}

public Employee(double s)
{
// calls the Employee(String, double) constructor
this("Employee #" + nextId, s);
}

// the default constructor
public Employee()
{
// name initialized to ""--see below
// salary not explicitly set--initialized to 0
// id initialized in initialization block
}

public String getName()
{
return name;
}

public double getSalary()
{
return salary;
}

public int getId()
{
return id;
}

private String name = ""; // instance variable initialization
private double salary;
private int id=8888;
private static int nextId;

// object initialization block
{
id = nextId;
nextId++;
}

// static initialization block
static
{
Random generator = new Random();
// set nextId to a random number between 0 and 9999
nextId = generator.nextInt(10000);
}
}
zhh200308 2003-08-29
  • 打赏
  • 举报
回复
先执行int a=3,
如果在constructor中再赋值的话就覆盖原来的。
jsjwql 2003-08-29
  • 打赏
  • 举报
回复
先执行带static的?
可能楼上的兄弟还没有听懂我的意思?
constructor是方法,而int a=3是表达式,它们作用都是初始化,但当建立一个对象的时候,先执行哪个初始话呢?
zhh200308 2003-08-29
  • 打赏
  • 举报
回复
<<//我想问的就是就我所知道的在类中很少有看到staticnitializer的方法,是不是想<<constructor一样编译器会生成一个默认的,如果有是什么样的?
当类被第一次加载时,进行静态初始化,仅初始化一次,如果你没有为它设置值,会
自动的设为0,false或null.

<<再就是,constructor与staticnitializer都是用于初始化的,但是constructor是在生成对<<象的时候才执行的,那staticnitializer是什么时候执行的,我对“类加载的时候”不是很<<理解?

当类被第一次加载时,进行静态初始化

<<如果我既有constructor也有直接用int a=3类似的方法进行了初始化,都是进行初始话,那<<在建立对象的时候先执行哪个初始话呢?

先执行带static的。

jsjwql 2003-08-29
  • 打赏
  • 举报
回复
有人吗??

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧