本章目标
•方法重载
•重载构造方法
•对象在内存中的存放形式
•this关键字
•静态成员,static关键字
•打包,package关键字
导入包,import关键字
回顾函数
•在Java中,函数即方法只要直接定义即可;
•Java中,函数被称为方法;
•定义一个方法的一般形式:
[访问权限] 返回值类型 方法名称(形参列表) {
方法主体;
}
•我们更关注的是方法原型,对于方法原型的三个主要组成部分应当明确区分:
>返回值类型
>方法名称
>形式参数
案例:
/*编写求绝对值的方法来求整数的绝对值*/
/*AbsoluteValue类,其中包含求绝对值的方法
Java中的任何方法都必须在类中定义*/
public class AbsoluteValue
{
/*求绝对值的方法*/
public int abs(int x)
{
return ((x >= 0) ? x : -x);
}
/*main方法,程序入口*/
public static void main(String[] args)
{
//必须先实例化类的对象,才可以调用到其中的成员方法
AbsoluteValue obj = new AbsoluteValue();
int a = -8, b;
b = obj.abs(a); //调用abs方法求a的绝对值
System.out.println(a + "的绝对值是" + b);
}
}
案例分析:
•在上面的案例中,我们已经定义了求整数绝对值的方法;
•但有时候,我们可能还需要求浮点数的绝对值,请问:可以继续使用这个方法吗?
•事实上是行不通的,这个方法只能求出整数的绝对值,对于浮点数,还需另外再定义求浮点数绝对值的方法。
修改案例:
public class AbsoluteValue {
/*求整数绝对值的方法*/
public int absOfInt(int x) {
return ((x >= 0) ? x : -x);
}
/*求浮点数绝对值的方法*/
public float absOfFloat(float x) {
return ((x >= 0) ? x : -x);
}
public static void main(String[] args) {
AbsoluteValue obj = new AbsoluteValue();
int a = -8, b;
b = obj.absOfInt(a);
System.out.println(a + "的绝对值是" + b);
float c = -3.14f, d;
d = obj.absOfFloat(c);
System.out.println(c + "的绝对值是" + d);
}
}
/**
如果还要求其它类型的
绝对值,就需要定义更
多的方法,这对于调用
者来说,将会是非常麻
烦的事情。
*/
方法重载
•用于定义一组方法,这些方法具有相同的名称,并执行类似的操作,但是却使用不同的参数列表;
•编译器会根据调用时传递的实际参数自动判断具体调用的是哪个重载方法,如:
方法重载的三大原则
/*abs方法的重载*/
int abs(int x) {……}
float abs(float x) {……}
double abs(double x) {……}
long abs(long x) {……}
•方法名相同
•参数不同(可以有三方面的不同)
>数量不同
>类型不同
>顺序不同
•同一作用域
•温馨提示:方法重载跟方法的返回值类型没有任何关系。也就是说,只有返回值不同的方法不能构成重载。
/*错误的方法重载*/
void fun(int x) {……};
int fun(int x) {……};
方法重载示例
public class AbsoluteValue {
public int abs(int x) { //重载方式1,求整数的绝对值
return ((x >= 0) ? x : -x);
}
public float abs(float x) { //重载方式2,求浮点数的绝对值
return ((x >= 0) ? x : -x);
}
public double abs(double x) { //重载方式3,求双精度数的绝对值
return ((x >= 0) ? x : -x);
}
public long abs(long x) { //重载方式4,求长整型数的绝对值
return ((x >= 0) ? x : -x);
}
public static void main(String[] args) {
AbsoluteValue obj = new AbsoluteValue();
int a = -8, b;
b = obj.abs(a);
System.out.println(a + "的绝对值是" + b);
float c = -3.14f, d;
d = obj.abs(c);
System.out.println(c + "的绝对值是" + d);
}
}
方法重载的两种方式之一
•利用不同数据类型的参数重载;
对于带有相同数量参数但参数类型不同的重载方法,编译器可以区分它们,如:
int square(int x) {……}
float square(float x) {……}
double square(double x) {……}
•只要所有参数式样都是唯一的,就可以使用多个重载;
•很多编程语言已经重载了输出方法,以便您可以用相同的函数名称输出任何类型的数据。
方法重载的两种方式之二
•利用不同数量的参数重载,如:
/*函数定义*/
int fun(int n1) {……}
int fun(int n1, int n2, int n3) {……}
/*函数调用*/
fun(a);
fun(x, y, z);
•将调用与参数最匹配的方法,如果没有方法得出最佳匹配,那么编译器将报错;
>编译器解决重载的方式与方法定义的顺序无关;
>重载不考虑方法的返回值类型。
方法重载的作用域规则
只有属于同一作用域范围内的方法才能构成重载 (一般是同一个类中)
关于方法重载的重要提示
请勿将功能完全不一样的方法进行重载!
重载构造方法
•方法重载的一个重要应用就是重载构造方法;
•可以定义一组构造方法,使其构成重载关系,从而方便使用者能够灵活机动地以各种不同的方式来实例化对象。
重载构造方法示例
class MyTime { //定义时间类
private int mHour, mMinute, mSecond; //三个成员变量,时、分、秒
public MyTime() { //构造方法重载1
mHour = 0;
mMinute = 0;
mSecond = 0;
}
public MyTime(int mHour) { //构造方法重载2
mHour = mHour;
mMinute = 0;
mSecond = 0;
}
public MyTime(int hour, int minute) { //构造方法重载3
mHour = hour;
mMinute = minute;
mSecond = 0;
}
public MyTime(int hour, int minute, int second) { //构造方法重载4
mHour = hour;
mMinute = minute;
mSecond = second;
}
public void display() { //显示时间信息的方法
System.out.println(mHour + ":" + mMinute + ":" + mSecond);
}
}
重载构造方法示例(续)
/*测试时间类*/
public class Test
{
/*main方法,程序入口*/
public static void main(String[] args)
{
//分别调用不同的构造方法来初始化时间对象
MyTime t1 = new MyTime(); //调用重载方式1
t1.display();
MyTime t2 = new MyTime(8); //调用重载方式2
t2.display();
MyTime t3 = new MyTime(8, 30); //调用重载方式3
t3.display();
MyTime t4 = new MyTime(8, 30, 30); //调用重载方式4
t4.display();
}
}
/*使用重载构造方法可以使初始化对象的方式灵活机动,大
大方便类的使用者。*/
对象在内存中的存放形式
每个对象都有自己独立的数据成员,但是所有的对象共享成员方法
this关键字
•既然所有的对象都共用相同的成员方法,那么在不同的对象都调用同一方法时,它是怎么确定要使用哪个对象的数据成员呢?
•每个成员方法都有一个隐含的this引用,它总是指向调用它的对象;
•关键字this给出用于调用成员方法的对象的地址;
•每当调用成员方法时,编译器会向this分配调用该方法的对象的地址;
•可以像使用任何引用那样使用this。
this引用示例
/*this示例,代码片段*/
public class Student //定义学生类
{
private String mName; //姓名
private int mAge; //年龄
public Student(String name, int age)
{
//隐式调用,等同于this.mName = name;
mName = name;
//显式调用,等同于mAge = age;
this.mAge = age;
}
……
}
静态成员变量
•在成员变量前加static关键字,可以将其声明为
静态成员变量;
•如果类中成员变量被定义为静态,那么
不论有多少个对象,静态成员变量只有一份内存拷贝,即所有对象共享该成员变量;
•静态成员变量的作用域只在类内部,但其
生命周期却贯穿整个程序。
静态成员变量示例:
class Dog
{
public static int count = 0; //静态成员变量
public Dog() //构造方法
{
count++;
}
}
public class Test
{
public static void main(String[] args)
{
System.out.println("当前狗的数量是:" + Dog.count);
Dog d1 = new Dog();
Dog d2 = new Dog();
System.out.println("当前狗的数量是:" + Dog.count);
}
}
静态成员变量的注意事项
•和程序同生命周期;
•在没有实例化对象时,可以通过类名访问静态成员变量;
•也可以通过对象访问静态成员变量,但不论使用的是哪个对象,访问到的都是同一个变量;
•
静态成员变量在声明时最好初始化,如果不进行初始化,
系统会默认初始化为0。
静态成员方法
•在成员方法前加static关键字,可以将其声明为静态成员方法;
•静态成员方法只能对类的静态成员变量进行操作;
•
静态成员方法没有this引用;
•在没有实例化对象时,可以通过类名访问静态成员方法。
静态成员方法示例:
class Dog {
private static int count = 0; //静态成员变量
public Dog() {
count++;
}
//显示数量的方法,静态成员方法
public static void displayCount() {
System.out.println("当前狗的数量是:" + count);
}
}
public class Test {
public static void main(String[] args) {
//没有实例化对象之前,直接通过类名调用静态成员方法
Dog.displayCount();
Dog d1 = new Dog();
Dog d2 = new Dog();
Dog.displayCount();
}
}
静态成员小结
•静态成员包括
静态数据成员和
静态成员方法;
•静态成员属于整个类而不是属于某个对象,它被该类的所有对象共享;
•访问静态成员时一般通过类名访问,也可以通过对象访问;
•
静态成员也受访问权限的约束;
•静态数据成员在使用之前应尽量初始化;
•
静态成员方法不能操作非静态成员;
•
静态成员方法没有this引用。
包
•有时候,类和类的名称可能发生冲突;
•Java提供了把类名空间划分为更容易管理的块的机制,这就是包;
•包允许将类组合成较小的单元,类似于文件夹;
•有助于避免命名冲突,分属不同包的类即便名称相同也不会引起误会;
能在包与包之间对于类的访问权限提供更有力的约束
使用package关键字打包
•可以使用package关键字将源文件中的类打入某个包中,语法是:
package 包名;
•该语句必须是整个源文件的第一条语句;
//将本源文件中的所有类打到mypkg包中
package mypkg;
class Student //定义学生类
{
……
}
•包中还可以包含下一级子包,这与文件目录体系非常相似。
包的编译和执行
缺省包
使用import关键字导入包
总结
作业
逻辑趣味思考题
包的编译和执行
•编译:
javac–d . Java文件名
说明: -d 参数指定路径 . 表示编译路径为当前目录.
执行:
java com.icss.字节码文件名
说明:执行时要说明字节码文件路径.
缺省包
•如果省略了package语句,类将保存在一个缺省的没有名称的包中;
•尽管缺省包很方便,但对于大型的程序,它是不恰当的;
请尽量为自己编写的类定义具体的包
使用import关键字导入包
•如要使用到某个包中的类,就需要使用import关键字将包或类显式地包括到程序中,有如下两种情况:
/*导入java包下的io子包中的所有类*/
import java.io.*;
/*导入mypkg包下的Student类,但并不导入该包中的其它类*/
import mypkg.Student;
……
•一个程序中允许有多条import语句,导入多个包或多个类。
总结
•方法重载可以方便方法的调用者,但方法重载应遵循三大原则:
>方法名相同
>参数列表不同
>属于同一作用域
•可以适当地重载构造方法,使初始化对象的方式更加灵活;
•this引用总是指向调用方法的对象本身;
•静态成员属于类而不是属于某个对象;
•总是将自己定义的类打入到具体的包中是良好的编程习惯;
•可以使用import语句导入需要的包或类。
作业
•在JAVA中定义一个类,在该类中有一系列的求绝对值的方法,要求使用方法重载?
•定义一个学生类,并将学生类的属性私有化同时为其提供公开的setter和getter,同时要求方法的参数名字要求要和属性名字一样!使用this关键字的编程!
•使用package对自己编写的类打包!使用import将其他的包中的类导入到程序中来
逻辑趣味思考题
•小明和他四个兄弟住在一起,每个人都有一个房间,假设每个房间都配有两个钥匙,除了每人拥有自己房间的一枚钥匙以外,如何放置剩下钥匙,且能让任何一个人任何时间都能顺利地进入每个房间呢?