你好,楼上说的不对,他没有仔细阅读代码。
10年积累的成都网站制作、成都网站设计、外贸营销网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站设计后付款的网站建设流程,更有渭南免费网站建设让你可以放心的选择与我们合作。
首先说明一点,你的程序是正确的。那个Derived是内部类,main方法属于Base,没有任何错误。
那么我就给你分析下为什么y的值是3。
程序的入口是main方法,那么首先执行:
Base b1 = new Base(); //调用Base的无参构造函数。此时 x = 1,y = 1
接着执行:
Derived d1 = new Derived();//因为Derved继承了Base,那么首先执行Base的构造方法
而Base的成员变量x属于对象,y属于类,所以x = 1, y = 2
同理在执行Derived d2 = new Derived(10, 20);之后
x = 1, y = 3
所以在打印b1的时候,x = 1 , y = 3
public class Demo
{
private int a; //实例变量
private static int a;//静态变量(也叫类变量)
public void fun1(){
//这个是实例方法
}
public void static fun2(){
//这个是静态方法(类方法)
}
}
public static void main(String[] args){
//这里调用实例方法
Demo demo =new Demo();
demo.fun1();
//这里调用静态方法
Demo.fun2();
}
其实静态变量或者方法还是挺好理解的,不知道你在写java应用程序时注意到没有,main()函数前面都要有一句public static void main(){}可见main()函数也是静态的。在程序中声明的静态变量和函数。都是和main()函数是同一级别的,可以直接通过类名调用,或者通过实例化对象,再通过对象调用。
普通的变量和函数就只能通过实例化变量调用了。
public class 静态常量
{
//静态变量!
private static int sum=88;
//静态常量!
private static final int con=99;
public static void main(string[] args)
{
system.out.println("变量变化前sum="+sum);
sum--;
system.out.println("变量变化后sum="+sum);
system.out.println("变化前con="+con);
//con++;这个注释一但取消就会报告错误:无法为最终变量con分配值
system.out.println("变化后con="+con);
}
}
个人的总结
1 静态变量只有一份被类的所有实例共享
2 静态变量的声明在编译时已经明确了内存的位置
3 延迟初始化是改变静态变量的值
引用
Java静态变量的初始化(static块的本质)
在网上看到了下面的一段代码:
1. public class Test {
2. static {
3. _i = 20;
4. }
5. public static int _i = 10;
6.
7. public static void main(String[] args) {
8. System.out.println(_i);
9. }
10. }
public class Test { static { _i = 20; } public static int _i = 10; public static void main(String[] args) { System.out.println(_i); } }
上述代码会打印出什么结果来呢?10还是20?本文将以此代码为引子,着重讨论一下静态变量的初始化问题。 楼主可以找组织先记下175再来记下161最后填写984就会出现扣裙问题1:静态变量如何初始化
Java类中可以定义一个static块,用于静态变量的初始化。如:
1. public class Test {
2. public static int _i;
3. static {
4. _i = 10;
5. }
6. }
public class Test { public static int _i; static { _i = 10; } }
当然最常用的初始化静态变量的操作是在声明变量时直接进行赋值操作。如:
1. public class Test {
2. public static int _i = 10;
3. }
public class Test { public static int _i = 10; }
那么上述两例在本质上有什么区别吗?回答是没有区别。两例代码编译之后的字节码完全一致,通过 “javap -c”查看到的字节码如下:
public class Test extends java.lang.Object{
public static int _i;
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init":()V
4: return
static {};
Code:
0: bipush 10
2: putstatic #2; //Field _i:I
5: return
}
通过字节码还可以看出,当类的定义中不含有static块时,编译器会为该类提供一个默认的static块。当然这是在含有静态变量初始化操作的前 提下。如果静态变量没有初始化操作,则编译器不会为之提供默认的static块。如:
1. public class Test {
2. public static int _i;
3. }
public class Test { public static int _i; }
其字节码的表现形式为:
public class Test extends java.lang.Object{
public static int _i;
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init":()V
4: return
}
由于静态变量是通过赋值操作进行初始化的,因此可以通过静态函数返回值的方式为其初始化。如:
1. public class Test {
2. public static int _i = init();
3.
4. private static int init() {
5. return 10;
6. }
7. }
public class Test { public static int _i = init(); private static int init() { return 10; } }
其本质与下面的代码相同:
1. public class Test {
2. public static int _i;
3. static {
4. _i = init();
5. }
6.
7. private static int init() {
8. return 10;
9. }
10. }
public class Test { public static int _i; static { _i = init(); } private static int init() { return 10; } }
问题2:JDK如何处理static块
类定义中可以存在多个static块吗?回答是可以。如:
1. public class Test {
2. public static int _i;
3. static {
4. _i = 10;
5. }
6.
7. public static void main(String[] args) {
8. }
9.
10. static {
11. _i = 20;
12. }
13. }
public class Test { public static int _i; static { _i = 10; } public static void main(String[] args) { } static { _i = 20; } }
此类编译之后的字节码为:
public class Test extends java.lang.Object{
public static int _i;
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
static {};
Code:
0: bipush 10
2: putstatic #2; //Field _i:I
5: bipush 20
7: putstatic #2; //Field _i:I
10: return
}
观察static{}部分可以看出,上例的代码与下面的代码效果一致:
1. public class Test {
2. public static int _i;
3.
4. public static void main(String[] args) {
5. }
6.
7. static {
8. _i = 10;
9. _i = 20;
10. }
11. }
public class Test { public static int _i; public static void main(String[] args) { } static { _i = 10; _i = 20; } }
此例可以证明,不仅类定义中可以有多个static块,而且在编译时编译器会将多个static块按照代码的前后位置重新组合成一个static 块。
问题3:如何看待静态变量的声明
静态变量存放在常量池之中。如何证明呢?如:
1. public class Test {
2. public static int _i = 10;
3. }
public class Test { public static int _i = 10; }
使用“javap -c -verbose”查看其字节码的内容如下:
public class Test extends java.lang.Object
SourceFile: "Test.java"
minor version: 0
major version: 49
Constant pool:
const #1 = Method #4.#14; // java/lang/Object."init":()V
const #2 = Field #3.#15; // Test._i:I
const #3 = class #16; // Test
const #4 = class #17; // java/lang/Object
const #5 = Asciz _i;
const #6 = Asciz I;
const #7 = Asciz init;
const #8 = Asciz ()V;
const #9 = Asciz Code;
const #10 = Asciz LineNumberTable;
const #11 = Asciz clinit;
const #12 = Asciz SourceFile;
const #13 = Asciz Test.java;
const #14 = NameAndType #7:#8;// "init":()V
const #15 = NameAndType #5:#6;// _i:I
const #16 = Asciz Test;
const #17 = Asciz java/lang/Object;
{
public static int _i;
public Test();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init":()V
4: return
LineNumberTable:
line 2: 0
static {};
Code:
Stack=1, Locals=0, Args_size=0
0: bipush 10
2: putstatic #2; //Field _i:I
5: return
LineNumberTable:
line 3: 0
}
我们看到,常量池中const #2指向的就是Test._i,也就是静态变量。静态变量被保存到常量池中的工作原理这里不深入讨论。在此需要注意的是:
* 静态变量的声明与初始化是两个不同的操作;
* 静态变量的声明在编译时已经明确了内存的位置。
如:
1. public class Test {
2. public static int _i = 10;
3. }
public class Test { public static int _i = 10; }
上述代码的本质可以视为:
1. public class Test {
2. // 静态变量的声明
3. public static int _i;
4.
5. // 静态变量的初始化
6. static {
7. _i = 10;
8. }
9. }
public class Test { // 静态变量的声明 public static int _i; // 静态变量的初始化 static { _i = 10; } }
由于静态变量的声明在编译时已经明确,所以静态变量的声明与初始化在编码顺序上可以颠倒。也就是说可以先编写初始化的代码,再编写声明代码。如:
1. public class Test {
2. // 静态变量的初始化
3. static {
4. _i = 10;
5. }
6.
7. // 静态变量的声明
8. public static int _i;
9. }
public class Test { // 静态变量的初始化 static { _i = 10; } // 静态变量的声明 public static int _i; }
对初始问题的解答
解答了上述三个问题,让我们再来看看开篇提到的问题。代码如下:
1. public class Test {
2. static {
3. _i = 20;
4. }
5. public static int _i = 10;
6.
7. public static void main(String[] args) {
8. System.out.println(_i);
9. }
10. }
public class Test { static { _i = 20; } public static int _i = 10; public static void main(String[] args) { System.out.println(_i); } }
其本质可以用下面的代码表示:
1. public class Test {
2. static {
3. _i = 20;
4. }
5. public static int _i;
6. static {
7. _i = 10;
8. }
9.
10. public static void main(String[] args) {
11. System.out.println(_i);
12. }
13. }
public class Test { static { _i = 20; } public static int _i; static { _i = 10; } public static void main(String[] args) { System.out.println(_i); } }
再简化一下,可以表示为:
1. public class Test {
2. public static int _i;
3.
4. static {
5. _i = 20;
6. _i = 10;
7. }
8.
9. public static void main(String[] args) {
10. System.out.println(_i);
11. }
12. }
public class Test { public static int _i; static { _i = 20; _i = 10; } public static void main(String[] args) { System.out.println(_i); } }
至此,代码已经明确告诉我们打印结果是什么了!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestClock extends JFrame{
/** Creates a new instance of TestClock */
public TestClock() {
JPanel jp=new JPanel();
final JLabel jl=new JLabel("0");
jp.add(jl);
add(jp,BorderLayout.CENTER);
JButton jbStart=new JButton("开始");
jbStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton j =(JButton)e.getSource();
j.setEnabled(false);
dt=new DamThread(new ClockThread(jl));
dt.start();
}
});
JButton jbPause=new JButton("暂停");
jbPause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton j=(JButton)e.getSource();
String s=(String)e.getActionCommand();
if(s.equals("暂停")){
dt.setStatus(ClockStatus.PAUSE);
j.setText("继续");
}else{
dt.setStatus(ClockStatus.CONTINUE);
j.setText("暂停");
}
}
});
JButton jbZero=new JButton("清零");
jbZero.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dt.setStatus(ClockStatus.ZERO);
}
});
JButton jbStop=new JButton("停止");
jbStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dt.setStatus(ClockStatus.STOP);
}
});
JPanel jp1=new JPanel();
jp1.add(jbStart);
jp1.add(jbPause);
jp1.add(jbZero);
jp1.add(jbStop);
add(jp1,BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) {
TestClock tc=new TestClock();
tc.setVisible(true);
}
DamThread dt;
}
class DamThread extends Thread{
public DamThread(ClockThread c){
this.ct=c;
ct.start();
this.setDaemon(true);
this.STATUS=ClockStatus.START;
}
public void run(){
while(ct.isAlive()){
CheckStatus();
}
}