1、
ClassAndObjectTest.java package ketangkehsi3; public class ClassAndObjectTest { public static void main(String[] args) { //创建类的实例,定义一个对象变量引用这一实例 MyClass obj = new MyClass(); //通过对象变量调用类的公有方法 obj.myMethod("Hello"); //给属性赋值 obj.setValue(100); //输出属性的当前值 System.out.println(obj.getValue()); //直接访问对象公有字段 obj.Information = "Information"; //输出对象公有字段的当前值 System.out.println(obj.Information); } } /** * 自定义Java类的示例 */ class MyClass { // 公有字段 public String Information = ""; // 自定义公有Java实例方法 public void myMethod(String argu) { System.out.println(argu); } // 定义属性:私有字段+get方法+set方法 private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
2、
早期我们经常这样定义变量 int value=100; 前面的示例中这样定义变量 MyClass obj = new MyClass();
两者有什么区别?
不一样。前面只定义一个变量,后者定义的对象变量。
3、请输入并运行以下代码,得到什么结果?
package ketangkehsi3; public class Test { public static void main(String []args) { Foo obj1=new Foo(); Foo obj2=new Foo(); System.out.println(obj1==obj2); } } class Foo { int value=100; }
原因:
当“==”施加于原始数据类型变量时,是比较变量所保存的数据是否相等
当“==”施加于引用类型变量时,是比较这两个变量是否引用同一对象。
引用代表地址,所以“==”实际上相当于比较两个引用类型变量中保存的对象地址是否相同。
4、对象变量也可以使用“==”判断两变量值是否相等吗?
package ketangkehsi3; public class dsa { public static void main(String []args){ int value1=100; int value2=100; System.out.println(value1==value2); } }
不相等
5、运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。
package ketangkehsi3; class Root { static{ System.out.println("Root的静态初始化块"); } { System.out.println("Root的普通初始化块"); } public Root() { System.out.println("Root的无参数的构造器"); } } class Mid extends Root { static{ System.out.println("Mid的静态初始化块"); } { System.out.println("Mid的普通初始化块"); } public Mid() { System.out.println("Mid的无参数的构造器"); } public Mid(String msg) { //通过this调用同一类中重载的构造器 this(); System.out.println("Mid的带参数构造器,其参数值:" + msg); } } class Leaf extends Mid { static{ System.out.println("Leaf的静态初始化块"); } { System.out.println("Leaf的普通初始化块"); } public Leaf() { //通过super调用父类中有一个字符串参数的构造器 super("Java初始化顺序演示"); System.out.println("执行Leaf的构造器"); } } public class TestStaticInitializeBlock { public static void main(String[] args) { new Leaf(); } }
静态初始化块的执行顺序:1.静态初始化块只执行一次。 2.创建子类型的对象时,也会导致父类型的静态初始化块的执行。
6、
如果一个类中既有初始化块,又有构造方法,同时还设定了字段的初始值,谁说了算?
如果父类有静态成员赋值或静态初始化块,执行静态成员赋值和静态初始化块。如果类有静态成员赋值或静态初始化块,执行静态成员赋值和静态初始化块将类的成员赋予初值。如果构造函数中年存在this()调用则执行。
7、使用上页幻灯片中定义的类,以下代码输出结果是什么?
package ketangkehsi3; public class InitializeBlockDemo { /** * @param args */ public static void main(String[] args) { InitializeBlockClass obj=new InitializeBlockClass(); System.out.println(obj.field); obj=new InitializeBlockClass(300); System.out.println(obj.field); } } class InitializeBlockClass{ //下面这句在初始化块之前与之后,会影响到field字段的初始值 //public int field=100; { field=200; } public int field=100; public InitializeBlockClass(int value){ this.field=value; } public InitializeBlockClass(){ }}
规律:所有类的变量都默认初始化null,数字类的原始数据类型默认初始化为0。
执行类的成员定义的默认值或类的初始化块,到底执行哪个要看哪一个排在前面。类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”。
8、有趣的问题
静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?
举例:
package ketangkehsi3; public class Example { int x = 3;//类的实例变量,初始化值为3 static int y = 4;//类的静态变量,初始化值为4 public static void method()//静态方法 { System.out.println("实例变量x = " + new Example().x);//在静态方法中访问类的实例变量需首先进行类的实例化 System.out.println("静态变量y = " + y);//在静态方法中可直接访问类的静态变量 } public static void main(String[] args) { Example.method(); Example ex = new Example(); System.out.println("x = " + ex.x); } }
运行截图:
结果分析:
类中静态的方法或者属性,本质上来讲并不是该类的成员,在java虚拟机装在类的时候,这些静态的东西已经有了对象,它只是在这个类中"寄居",不需要通过类的构造器(构造函数)类实现实例化;而非静态的属性或者方法,在类的装载是并没有存在,需在执行了该类的构造函数后才可依赖该类的实例对象存在。
在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
public static void main(String[] args)
{
Example.method();
Example ex = new Example();
System.out.println("x = " + ex.x);
}
}
9、代码(StrangeIntegerBehavior.java)输出诡异的结果,原因何在?
package ketangkehsi3; public class StrangeIntegerBehavior { public static void main(String[] args) { Integer i1=100; Integer j1=100; System.out.println(i1==j1); Integer i2=129; Integer j2=129; System.out.println(i2==j2); } }
原因:在通过valueof方法创建Integer类型对象时,取值范围为[-128,127],数值在这个区间里,指针指向IntegerCache.cache中已经存在的对象引用,当数值超出这个范围,就会创建一个新的对象。而对对象使用“==”是判断两个对象是否是同一个,所以i1 == j1,i2 != j2。
10、总结Java字段初始化的规律
(1)执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”。
(2)执行类的构造函数。
11、Integer类的装箱和拆箱是怎么样实现的?
package ketangkehsi3; public class BoxAndUnbox { /** * @param args */ public static void main(String[] args) { int value=100; Integer obj=value; //装箱 int result=obj*2; //拆箱 } }
所谓装箱,就是把基本类型用他们相对应的引用类型包装起来,使他们可以具有对象的特质,如我们可以把int型包装成Integer类的对象,或者把double包装成Double等等。
所谓拆箱,就是跟装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为值类型的数据。
深入剖析链接:http://www.cnblogs.com/dolphin0520/p/3780005.html