THINKING IN JAVA 学习笔记(四)

第五章 初始化与清理

5.1 使用构造器确保初始化

使用构造器在创建对象的时候完成初始化。构造器的名称必须和类名完全相同,所以“每个方法首字母小写”的编码风格并不适用于构造器。不接受任何参数的构造器叫默认构造器,或者叫无参构造器。使用构造器有助于减少错误,并使代码更易阅读。

构造器是一种特殊类型的方法,因为它没有返回值,这和void有明显不同。对于void,尽管方法本身不会自动返回什么,但仍然可以选择让它返回别的东西(意思是你也可以不用void,选择Stringint等返回类型)。构造器不会返回任何东西,你别无选择。The constructor is an unusual type of method because it has no return value. This is distinctly different from a void return value, in which the method returns nothing but you still have the option to make it return something else. Constructors return nothing and you don’t have an option.

5.2 方法重载

既然构造器的名字只能和类名一样,那我想要用多种方式创建一个对象该怎么办?为了达到这个目的,引入“方法重载”的概念。方法重载处理可以用于构造器,也适用于其他方法。

5.2.1 区分重载方法

重载方法的名字都相同,Java如何区分?使每一个重载的方法都有一个独一无二的参数类型列表即可。

参数的类型、个数甚至顺序都可以区分两个重载方法,但是一般情况下不要用参数顺序区分,因为这样会使代码难以维护。

5.2.2 涉及基本类型的重载

隐式转换(扩展转换)会把小类型自动提升为大类型,在重载时会造成一些混淆:

  1 //: initialization/PrimitiveOverloading.java
  2 // Promotion of primitives and overloading.
  3 import static net.mindview.util.Print.*;
  4 
  5 public class PrimitiveOverloading {
  6   void f1(char x) { printnb("f1(char) "); }
  7   void f1(byte x) { printnb("f1(byte) "); }
  8   void f1(short x) { printnb("f1(short) "); }
  9   void f1(int x) { printnb("f1(int) "); }
 10   void f1(long x) { printnb("f1(long) "); }
 11   void f1(float x) { printnb("f1(float) "); }
 12   void f1(double x) { printnb("f1(double) "); }
 13 
 14   void f2(byte x) { printnb("f2(byte) "); }
 15   void f2(short x) { printnb("f2(short) "); }
 16   void f2(int x) { printnb("f2(int) "); }
 17   void f2(long x) { printnb("f2(long) "); }
 18   void f2(float x) { printnb("f2(float) "); }
 19   void f2(double x) { printnb("f2(double) "); }
 20 
 21   void f3(short x) { printnb("f3(short) "); }
 22   void f3(int x) { printnb("f3(int) "); }
 23   void f3(long x) { printnb("f3(long) "); }
 24   void f3(float x) { printnb("f3(float) "); }
 25   void f3(double x) { printnb("f3(double) "); }
 26 
 27   void f4(int x) { printnb("f4(int) "); }
 28   void f4(long x) { printnb("f4(long) "); }
 29   void f4(float x) { printnb("f4(float) "); }
 30   void f4(double x) { printnb("f4(double) "); }
 31 
 32   void f5(long x) { printnb("f5(long) "); }
 33   void f5(float x) { printnb("f5(float) "); }
 34   void f5(double x) { printnb("f5(double) "); }
 35 
 36   void f6(float x) { printnb("f6(float) "); }
 37   void f6(double x) { printnb("f6(double) "); }
 38 
 39   void f7(double x) { printnb("f7(double) "); }
 40 
 41   void testConstVal() {
 42     printnb("5: ");
 43     f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5); print();
 44   }
 45   void testChar() {
 46     char x = 'x';
 47     printnb("char: ");
 48     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 49   }
 50   void testByte() {
 51     byte x = 0;
 52     printnb("byte: ");
 53     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 54   }
 55   void testShort() {
 56     short x = 0;
 57     printnb("short: ");
 58     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 59   }
 60   void testInt() {
 61     int x = 0;
 62     printnb("int: ");
 63     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 64   }
 65   void testLong() {
 66     long x = 0;
 67     printnb("long: ");
 68     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 69   }
 70   void testFloat() {
 71     float x = 0;
 72     printnb("float: ");
 73     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 74   }
 75   void testDouble() {
 76     double x = 0;
 77     printnb("double: ");
 78     f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print();
 79   }
 80   public static void main(String[] args) {
 81     PrimitiveOverloading p =
 82       new PrimitiveOverloading();
 83     p.testConstVal();
 84     p.testChar();
 85     p.testByte();
 86     p.testShort();
 87     p.testInt();
 88     p.testLong();
 89     p.testFloat();
 90     p.testDouble();
 91   }
 92 } /* Output:
 93 5: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double)
 94 char: f1(char) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double)
 95 byte: f1(byte) f2(byte) f3(short) f4(int) f5(long) f6(float) f7(double)
 96 short: f1(short) f2(short) f3(short) f4(int) f5(long) f6(float) f7(double)
 97 int: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double)
 98 long: f1(long) f2(long) f3(long) f4(long) f5(long) f6(float) f7(double)
 99 float: f1(float) f2(float) f3(float) f4(float) f5(float) f6(float) f7(double)
100 double: f1(double) f2(double) f3(double) f4(double) f5(double) f6(double) f7(double)
101 *///:~
View Code

常值5被当做int值,如果重载的方法中有正好接受int型参数的,那么就会调用它。如果没有,而且传入的实参类型比形参类型小,实参类型就会隐式转换成较大类型(最接近的),调用这个类型参数的方法。

char类型不太一样,如果找不到正好接受char参数的重载方法,char型直接变成int

如果传入的实参比形参类型还大

 1 //: initialization/Demotion.java
 2 // Demotion of primitives and overloading.
 3 import static net.mindview.util.Print.*;
 4 
 5 public class Demotion {
 6   void f1(char x) { print("f1(char)"); }
 7   void f1(byte x) { print("f1(byte)"); }
 8   void f1(short x) { print("f1(short)"); }
 9   void f1(int x) { print("f1(int)"); }
10   void f1(long x) { print("f1(long)"); }
11   void f1(float x) { print("f1(float)"); }
12   void f1(double x) { print("f1(double)"); }
13 
14   void f2(char x) { print("f2(char)"); }
15   void f2(byte x) { print("f2(byte)"); }
16   void f2(short x) { print("f2(short)"); }
17   void f2(int x) { print("f2(int)"); }
18   void f2(long x) { print("f2(long)"); }
19   void f2(float x) { print("f2(float)"); }
20 
21   void f3(char x) { print("f3(char)"); }
22   void f3(byte x) { print("f3(byte)"); }
23   void f3(short x) { print("f3(short)"); }
24   void f3(int x) { print("f3(int)"); }
25   void f3(long x) { print("f3(long)"); }
26 
27   void f4(char x) { print("f4(char)"); }
28   void f4(byte x) { print("f4(byte)"); }
29   void f4(short x) { print("f4(short)"); }
30   void f4(int x) { print("f4(int)"); }
31 
32   void f5(char x) { print("f5(char)"); }
33   void f5(byte x) { print("f5(byte)"); }
34   void f5(short x) { print("f5(short)"); }
35 
36   void f6(char x) { print("f6(char)"); }
37   void f6(byte x) { print("f6(byte)"); }
38 
39   void f7(char x) { print("f7(char)"); }
40 
41   void testDouble() {
42     double x = 0;
43     print("double argument:");
44     f1(x);f2((float)x);f3((long)x);f4((int)x);
45     f5((short)x);f6((byte)x);f7((char)x);
46   }
47   public static void main(String[] args) {
48     Demotion p = new Demotion();
49     p.testDouble();
50   }
51 } /* Output:
52 double argument:
53 f1(double)
54 f2(float)
55 f3(long)
56 f4(int)
57 f5(short)
58 f6(byte)
59 f7(char)
60 *///:~
View Code

  如果不进行显式转换(窄化转换),编译器会报错

5.2.3 不用返回值区分重载方法

void f() {}
int f() {return 1;}

上面两个方法好像挺好区分的,只要编译器根据语境判断语义,比如 int x = f(); ,不就可以区分了吗?(实际不能按上面这样写)

但有时候调用方法我们根本不关心返回值,比如这样调用: f(); ,编译器就没法判断了,所以不用返回值区分重载方法。

 

猜你喜欢

转载自www.cnblogs.com/lykxbg/p/10288005.html