第五讲 对象的初始化
主要内容
用构造方法确保初始化 方法的重载 this关键字 类中成员变量的默认值 对象的初始化过程 |
用构造方法确保初始化
缺省构造方法
javap.exe观察类框架
bin目录下的javap.exe,是一个反编译的类察看器。
D:\Javawork\Lesson4>javap Person
Compiled from "Person.java"
class Person extends java.lang.Object{
int sex;
int salary;
Person();
void employed();
}
观察:类框架中多了哪一项?
构造方法的初步认识
² 构造方法的名字和类名相同,无类型修饰,没有返回值。
² 凡Java类都有构造方法,如果程序中没定义,编译器会自动提供缺省的构造方法。
² 类中无定义构造方法时,编译时自动添加缺省的构造方法
² 缺省的构造方法不带参数。
主动在类中引入构造方法
阅读程序分析结果
class Person2{
int salary;
Person2(){
System.out.println("output of constructor");
}
void employed(){
System.out.print("Work state:");
if (salary==0) System.out.println("no job");
else System.out.println("job");
}
public static void main(String[] a){
Person2 p1=new Person2();
p1.salary=900;
p1.employed();
}
}
问题:在创建对象时,能否直接将薪水传递过去?试修改实现。
思考 1. 构造方法有什么用? 2. 每个类都有构造方法吗? 3. 构造方法的命名和类型修饰? 4. 构造方法的执行时机? 5. 如果希望创建对象时,传递给对象中的变量初值,怎么实现? 6. 回顾new运算,new 类名(参数),其中的参数什么时候带,什么时候不带? 7. 如果一个类定义了带参的构造方法,可以用new 类名()创建该类的对象吗? |
说明:构造方法不可声明返回类型(包括void)。如说明编译器将把它看作为一个一般的方法,而不是构造方法。
练习:构造一个Circle类,可接受变量半径,并有求圆面积的方法getS和求圆周长的方法getL。通过Circle类的实例化对象,分别求半径为:1、1.5、2.5的圆面积和圆周长。
类中方法的重载
成员方法的重载
重载:一词多义。
方法重载:同一个方法名,被赋予了多个意义。多个同名方法对应于不同的处理任务。
例:阅读和分析程序运行结果
class TestOL{
int x;
void func(){System.out.println("no arg");}
String func(int i){
return "arg is "+i;
}
void func(String s){
System.out.println(s);
}
public static void main(String[] a){
TestOL c=new TestOL();
c.func();
c.func(c.func(100));
}
}
方法重载设计要点
² 方法名相同
² 参数不同或者返回类型不同
int f(){…} void f(){…}
void f(int a,int b){…} void f(String c){…}
重载时方法的窄化转型
class TestOL{
void func(double x){System.out.println(x+" is double");}
void func(float x){ System.out.println(x+" is float");}
void func(int x){System.out.println(x+" is int");}
public static void main(String[] a){
TestOL c=new TestOL();
c.func(1);
c.func(2.5);
c.func(3.5f);
}
}
结论:窄化转型,即传递的实参“小于”方法中声明的形参,实参就会自动提升一级。
思考
1. 方法重载的特征是什么? 2. 方法重载有何意义? 3. 如果例2的main方法中添加语句c.func(‘a’);,会是什么结果? 4. 如果例2的类定义中,注释掉前面两个func方法,又会是什么结果? |
练习:
1、构造一个包含有求累加和方法sum的类MyCal,sum方法可接受一个或两个整型参数,如果是一个参数,则是从自然数1开始的累加;如果是两个参数m和n,求的是从其中较小数到较大数的累加和。
2、试用上类。
构造方法重载
同一个类可有多个构造方法,但只有一个构造方法在创建对象时执行。
class Flower{
Flower(String c){
System.out.println("It's a "+c+" flower.");
}
Flower(String s,String c){
System.out.println("It's a "+s+" "+c+" flower." );
System.out.println("How beautiful!");
}
}
class Test{
public static void main(String[] aa){
new Flower("red");
new Flower("little","yellow");
new Flower("big","red");
}
}
思考 1. 一个类的构造方法可以重载吗? 2. 创建对象时,类中所有的构造方法都会顺序执行吗? 3. 创建对象时如何决定运行哪个构造方法? 4. 构造方法的执行时机? |
练习一:
1、构造一个可接受一个或两个参数的矩形类Square,含求矩形面积的方法。如果传递过来一个参数,作正方形处理;
2、实例化矩形类,求:(1)长2.3,宽4.5的矩形面积。(2)边长为7.6的正方形面积。
练习二:设计一个类,分别将三角形的三条边作为属性,并能计算面积。(默认为勾三股四弦五的直角三角形,一个参数时默认为边长为1的等边三角形,三个参数时分别为三条边长)
class Triangle{
double a,b,c;
Triangle(){
}
Triangle(double x){
}
Triangle(double a,double b,double c){
}
double getS(){
}
}
this关键字
在方法内使用,表示调用方法的这个对象。
² this.变量名-------访问这个对象的变量
² this.方法名(参数);----------访问这个对象的方法
² this(参数);----------调用这个对象的同名成员方法
程序一:
class TestA{
TestA(){
int i=7;
System.out.println(i+" "+this.i);
this.i=3;
}
int i=1;
public static void main(String[] args){
System.out.println(new TestA().i);
}
}
程序二:
class TestThis{
int a;
int b;
TestThis(int a,int b){
this.a=a;
this.b=b;
System.out.println(a+"----"+b+"\t"+this.sum());
}
TestThis(int a){
this(1,a);
}
int sum(){
int s=0;
for(int i=a;i<=b;i++)s+=i;
return s;
}
public static void main(String[] aa){
new TestThis(10,20);
new TestThis(100);
}
}
思考 1. 方法中的变量与类的成员变量可否同名? 2. 若同名时,在方法中如何访问成员变量? 3. 如何在类方法中调用同类中的方法? |
类中成员变量的默认值
类中的成员变量可以在类定义时给初值。
如果没有对基本数据类型的成员预先赋初值,则在创建变量时自动初始化。要点:
² 数值型,值为0
² 布尔型,值为false
² 字型串,值为空(null)
class TestInit{
int x;
String s;
boolean f;
public static void main( String[ ] args ){
TestInit l=new TestInit();
System.out.println( "\nx is " + l.x );
System.out.println( "s is " + l.s );
System.out.println("f is "+ l.f);
}
}
程序可以正确编译和运行!
如果一个变量在方法中定义,那么使用这个变量前必须赋值。
class TestInit{
public static void main( String[ ] args ){
int x;
System.out.println( "\nx is " + x );
}
}
错误信息:variable x might not have been initialized
对象的初始化过程
对象的基本初始化过程
² 初始化时涉及到成员变量和构造方法;
² 实例变量的初始化在构造方法之前。
程序一:
class TestInit{
int x=3;
TestInit(){
x=5;
}
public static void main( String[ ] args ){
TestInit t=new TestInit();
System.out.println(t.x );
}
}
class TestInit{
TestInit(int a){
x=a;
}
public static void main( String[ ] args ){
TestInit t=new TestInit(5);
System.out.println( t.x );
}
int x=3;
}
程序二:
class Tag{
Tag(int m){
System.out.println("Tag("+m+")");
}
}
class Card{
Tag t1=new Tag(1);
Card(){
System.out.println("Card()");
t3=new Tag(33);
}
Tag t2=new Tag(2);
void f(){
System.out.println("f()");
}
Tag t3=new Tag(3);
}
class TestInit2{
public static void main(String[] aa){
Card t=new Card();
t.f();
}
}
静态变量的初始化
² 类中的静态成员变量的初始化在第一次创建变量,或直接由类调用时进行
² 静态变量只初始化一次
class Bow{
Bow(int m){
System.out.println("Bow("+m+")");
}
void f(int m){
System.out.println("f("+m+")");
}
}
class Table{
Bow b1=new Bow(1);
Table(){
System.out.println("Table()");
b2.f(1);
}
static Bow b2,b3;
static{
b2=new Bow(2);
b3=new Bow(3);
}
}
class TestInit{
public static void main(String[] aa){
System.out.println("Creating new Table()");
new Table();
System.out.println("Creating new Table()");
new Table();
}
}
思考 1. 对象的初始化在什么时候进行? 2. 静态变量和实例变量的初始化时机? 3. 实例变量和构造方法哪个先初始化? 4. 除了构造方法外,通常的成员方法会自动初始化吗? 5. 类有多个成员变量,这些变量的初始化顺序? |