练习1:创建一个类,包含一个未初始化的String引用。验证该引用被java初始化成为了null。
代码:
public class TestNewClassWithNULL { String a; public static void main(String[] args) { TestNewClassWithNULL newClassWithNULL = new TestNewClassWithNULL(); System.out.println(newClassWithNULL.a); } }
输出:
null
练习2:创建一个类,他包含一个在定义时就被初始化的String域,以及另一个通过构造器初始化的String域,这两种方式有何差异?
代码
public class TestNewClassWithTwoString { String a = "a"; String b; public TestNewClassWithTwoString(){ System.out.println(a); System.out.println(b); b = "b"; } public static void main(String[] args) { TestNewClassWithTwoString testNewClassWithTwoString = new TestNewClassWithTwoString(); System.out.println(testNewClassWithTwoString.a); System.out.println(testNewClassWithTwoString.b); } }
输出:
a
null
a
b
区别:在创建类对象时,定义时被初始化的对象已经被创建(指向常量,不为空),构造器初始化需要首先指向新创建的常量才能被初始化。
练习3:创建一个带默认构造器(无参构造器)的类,在构造器中打印一条消息。为该类创建一个对象
代码:
public class TestConstructor { public TestConstructor(){ System.out.println("non param"); } public static void main(String[] args) { TestConstructor testConstructor = new TestConstructor(); } }
输出:
non param
练习4:为前一个练习中的类添加一个重载构造器,令其接受一个字符串参数,并在构造器中把你自己的消息和接受的参数信息一起打印出来。
代码:
public class TestConstructor { public TestConstructor(){ System.out.println("non param"); } public TestConstructor(String param){ System.out.println("receive param:" + param); } public static void main(String[] args) { TestConstructor testConstructor = new TestConstructor(); TestConstructor testConstructor1 = new TestConstructor("hahaha"); } }
输出:
non param
receive param:hahaha
练习5:创建一个名为Dog的类,他具有重载的bark()方法。此方法根据不同的基本数据类型进行重载,并根据被调用的版本,打印出不同类型的狗吠(barking),咆哮(howling)等信息。编写main()来调用所有不同版本的方法。
代码:
public class Dog { public Dog(boolean bark) { System.out.println("bark?" + bark); } public Dog(byte bark) { System.out.println("byte bark wee"); } public Dog(char bark) { System.out.println("char bark quietly"); } public Dog(short bark) { System.out.println("short bark within earshot"); } public Dog(int bark) { System.out.println("int bark normally"); } public Dog(long bark) { System.out.println("long bark excitingly"); } public Dog(float bark) { System.out.println("float bark loudly"); } public Dog(double bark) { System.out.println("double bark deafening"); } public static void main(String[] args) { new Dog(false); new Dog((byte) 1); new Dog('a'); new Dog((short) 1); new Dog(1); new Dog((long) 1); new Dog((float) 1); new Dog((double) 1); } }
输出:
bark?false
byte bark wee
char bark quietly
short bark within earshot
int bark normally
long bark excitingly
float bark loudly
double bark deafening
练习6:修改前一个练习的程序,让两个重载方法各自接受两个类型的不同的参数,但两者顺序相反,验证其是否工作。
代码:
public class Dog { public Dog(boolean bark) { System.out.println("bark?" + bark); } public Dog(byte bark) { System.out.println("byte bark wee"); } public Dog(char bark, int times) { System.out.println("char bark quietly" + times); } public Dog(short bark) { System.out.println("short bark within earshot"); } public Dog(int bark, char times) { System.out.println("int bark normally" + times); } public Dog(long bark) { System.out.println("long bark excitingly"); } public Dog(float bark) { System.out.println("float bark loudly"); } public Dog(double bark) { System.out.println("double bark deafening"); } public static void main(String[] args) { new Dog(false); new Dog((byte) 1); new Dog('a', 66); new Dog((short) 1); new Dog(1, '6'); new Dog((long) 1); new Dog((float) 1); new Dog((double) 1); } }
输出:
bark?false
byte bark wee
char bark quietly66
short bark within earshot
int bark normally6
long bark excitingly
float bark loudly
double bark deafening
练习7:创建一个没有构造器的类,并在main()中创建其对象,用以验证编译器是否真的自动加入的默认构造器。
答:显然
练习8:略
练习9:this构造器
代码:
public class TestConstructor { public TestConstructor(){ this(11); } public TestConstructor(int a){ System.out.println(a); } public static void main(String[] args) { TestConstructor testConstructor = new TestConstructor(); } }
输出:
11
练习10:编写具有finalize()方法的类,并在方法中打印消息。在main()中为该类创建一鞥对象。试图解释这个程序的行为。
代码
public class HumanResource { /** * 被优化了 */ @Override protected void finalize() { System.out.println("optimized"); } public static void main(String[] args) { HumanResource humanResource = new HumanResource(); } }
练习11:修改前一个练习的程序,让你的finalize()总是被调用
代码:
public class HumanResource { public int age; public HumanResource(int age) { this.age = age; } /** * 被优化了 */ @Override protected void finalize() { System.out.println("optimized"); } public static void main(String[] args) { HumanResource humanResource = new HumanResource(40); // if (humanResource.age > 35) { //引用置空时很有必要的,否则不会被优化掉 humanResource = null; // } System.gc(); System.out.println("finish"); } }
输出:
finish
optimized
代表没有用了就被优化掉了。
练习12:编写名为Tank的类,此类的状态可以是“满的”或“空的”,其终结条件是对象被清理的时必须处于空状态。请编写finalize()以检验终结条件是否成立。在main()中测试Tank可能发生的几种使用方式。
代码
public class Tank { boolean isFull = false; public Tank(boolean isFull) { this.isFull = isFull; } @Override protected void finalize() { if (!isFull) { System.out.println("is empty"); } } public static void main(String[] args) { new Tank(false); System.gc(); } }
输出:
is empty
练习13:验证静态代码块
代码:
public class TestStaticBlock { public static class Cup { public Cup(int maker) { System.out.println("Cup(" + maker + ")"); } void f(int maker) { System.out.println("f(" + maker + ")"); } } public static class Cups{ static Cup cup1; static Cup cup2; static { cup1 = new Cup(1); cup2 = new Cup(2); } Cups(){ System.out.println("cups"); } } public static void main(String[] args) { Cups.cup1.f(99); } static Cups cups = new Cups(); }
输出:
Cup(1)
Cup(2)
cups
f(99)
练习14:编写一个类,拥有两个静态字符串域,其中一个在定义处初始化,另一个在静态块中初始化。现在,加入一个静态方法用以打印出两个字段值。证明他们都在使用前完成了初始化动作。
代码
public class TestStaticBlock { public static class Cup { public Cup(int maker) { System.out.println("Cup(" + maker + ")"); } void f(int maker) { System.out.println("f(" + maker + ")"); } } public static class Cups{ static Cup cup1; static Cup cup2 = new Cup(2); static { cup1 = new Cup(1); } Cups(){ System.out.println("cups"); } } public static void main(String[] args) { Cups.cup1.f(99); } static Cups cups = new Cups(); }
输出
Cup(2)
Cup(1)
cups
f(99)
练习15:编写一个含有字符串域的类,并采用实例化初始化的方式进行初始化。
代码:
public class TestStaticBlock { public static class Cup { public Cup() { System.out.println("no maker"); } public Cup(int maker) { System.out.println("Cup(" + maker + ")"); } } public static class Cups { Cup cup1; Cup cup2 = new Cup(2); { cup1 = new Cup(1); System.out.println("complete cup 2"); } Cups() { System.out.println("cups"); } Cups(int i){ System.out.println("cups : " + i); } } public static void main(String[] args) { System.out.println("start main"); new Cups(); System.out.println("cups complete"); new Cups(1); System.out.println("cups 1 complete"); } }
输出:
start main
Cup(2)
Cup(1)
complete cup 2
cups
cups complete
Cup(2)
Cup(1)
complete cup 2
cups : 1
cups 1 complete
练习16:创建一个String对象数组,并为每一个元素都赋值一个String。用for循环来打印该数组。
代码:
public class TestStringArray { String[] strings = new String[]{"1", "2", "aaa", "bao"}; public static void main(String[] args) { TestStringArray testStringArray = new TestStringArray(); for (String str : testStringArray.strings) { System.out.println(str); } } }
输出:
1
2
aaa
bao
练习17:创建一个类,他有一个接受一个String参数的构造器。在构造阶段,打印该参数。创建一个该类的对象引用数组,但是不实际去创建对象赋值给给该数组。当运行程序时,请注意来自对该构造器的调用中的初始化消息是否打印了出来。
练习18:赋值给引用对象。
代码
import java.util.Arrays; public class TestStringArray { String[] strings; public TestStringArray(String[] strings) { System.out.println(Arrays.toString(strings)); this.strings = strings; } public static void main(String[] args) { TestStringArray testStringArray = new TestStringArray(new String[1]); //未初始化str[0],会空指针 // for (String str : testStringArray.strings) { // System.out.println(str); // } } }
输出
[null]
练习19:写一个类,接受一个可变的参数的String数组,验证你可以向该方法传递一个逗号分隔的String列表或者一个String[]。
代码:
import com.sun.istack.internal.Nullable; import java.util.Arrays; public class TestStringArray { public TestStringArray(String... strings) { if (strings.length == 0) { System.out.println("non param"); return; } for (String str : strings) { System.out.println(str); } } public static void main(String[] args) { new TestStringArray(); new TestStringArray("a"); new TestStringArray("a", "bbb"); new TestStringArray(new String[]{"ccc", "ddd", "fff"}); } }
输出:
non param
a
a
bbb
ccc
ddd
fff
练习20:创建一个使用可变参数列表的而不是普通的main()语法的main()。打印所产生的args数组的所有元素,并用各种不同数量的命令行参数来测试他。
代码
public class TestStringArray { public static void main(String... args) { if(args.length == 0){ System.out.println("non param"); } for(String str:args){ System.out.println(str); } } } 配置
输出
test1
test2
练习21:创建一个enum,它包含纸币中最小面值的6种类型。通过values()循环并打印每一个值及其ordinal()。
练习22:在前面的例子种,为enum写一个switch语句,对于每一个case,输出该特定的货币描述
代码
public class TestEnum { public static enum RMB{ ONE,FIVE,TEN,TWENTY,FIFTY,HUNDRED } public static void main(String[] args) { for (RMB rmb:RMB.values()){ System.out.println(rmb.ordinal()); switch (rmb){ case ONE: System.out.println("一元"); break; case FIVE: System.out.println("五元"); break; case TEN: System.out.println("十元"); break; case TWENTY: System.out.println("二十元"); break; case FIFTY: System.out.println("五十元"); break; case HUNDRED: System.out.println("一百元"); break; } } } }
输出
0
一元
1
五元
2
十元
3
二十元
4
五十元
5
一百元