Java笔记 第四章 Java面向对象编程基础 第二部分(类的成员变量和方法)
类的成员变量和方法是组成类的基本元素。成员变量描述类的属性,方法则获取或改变属性的值。本节学习如何声明类的成员变量和如何使用类的成员变量。
1、访问修饰符:public,private,protect,default
(1)public:公共的,访问权限最宽。被它修饰的类、属性、方法不仅可以跨类访问,而且可以允许跨包的访问。
(2)private:私有的,访问权限最窄。被它修饰的类、属性、方法只能被该类的对象访问,其子类不允许访问,更不允许跨包访问。
(3)protect:保护型,访问权限介于public和private之间。被它修饰的类、属性、方法只能被类本身的方法及子类方法访问,允许子类在不同的包中访问。
(4)default:默认访问模式,即不加任何的访问修饰符。在模式下只允许在同一个包中进行访问。
2、构造方法
构造方法是类中一个特殊的方法,与其他方法不同,构造方法主要用来初始化类,创建类的实例(类的对象,即对象实例化)。构造方法的名字和类的名字是相同的,并且没有返回值类型。在构造方法前,只可以使用访问修饰符public、private、protect。
在Java中创建一个类,要让这个类工作,必须创建类的对象。换句话说,类是某一些对象的抽象集合体,对象是满足类特征属性的一个实际存在的实例。例如:动物类是一个抽象的集合,而猫、狗就是具备动物类的属性的一个实例,即动物类的对象。Java程序创建一个类的对象,就需要调用构造方法来实现,其过程实际上就是程序内部为所创建的对象分配空间。
构造方法的写法如下所示:
class Student
{
private String name; //姓名
private char sex; //性别
private String birthday; //生日
public Student() //构造方法
{
name = “zhangsan”; //初始化
sex = “man”;
birthday = “2015/12/22”;
}
...... ;
public static void main(String argv[])
{
student stu = new Student(); //创建类对象
}
}
这段代码创建了一个Student的对象stu,从而stu对象就代表了一个具体学生的实例,该学生姓名为“zhangsan”,性别“man”,生日“2015/12/22”。
(如果一个类中没有定义类的构造方法,系统会为这个类自动创建一个缺省的默认构造器,该构造器参数及方法体均为空。)
3、定义变量
Java中存在两种变量,即成员变量和局部变量。
(1)成员变量:在方法体外定义,即类所拥有的变量,可由系统自动初始化。
(2)局部变量:在方法体内定义,即方法拥有的变量,只能由程序员为其指定初始值。
成员变量和局部变量由于所属对象的生命周期不同,因此其生存周期也不相同。成员变量在类的实例被创建时产生,其生命周期和该类的实例对象的生命周期相同;局部变量在定义该变量的方法被调用时创建,在该方法调用结束后随之消失。
代码片段如下所示:
class Demo01
{
private int a; //声明成员变量a
Protect int b = 20; //声明并初始化成员变量b
public void method()
{
int c = 0; //声明并初始化局部变量c
......;
}
......;
}
4、定义成员方法
成员方法可以用来获取或修改对象的属性,同时也可以用来接收其他对象的信息,以及向其他的对象发送消息。在通常情况下成员方法中都包含了一组相关的语句,用来执行相应的操作。
方法声明的基本格式如下:
返回值类型 方法名(参数1,参数2,...,参数n)
{
......; //方法体
}
任务:创建Employee雇员类的一个对象emp,表示一个特定的员工,同时在Employee雇员类中,定义三个成员方法,用来输出emp对象的属性值。
代码:成员方法的使用:Employee.java
public class Employee
{
private String name; //定义成员变量
private double salary;
private String hireDay;
public Employee() //构造方法
{
name = "Zhang Xiao"; //定义并初始化局部变量
salary = 6000.00;
hireDay = "2015/13/14";
}
public void showName() //第一个成员方法:输出雇员姓名
{
System.out.println("Name:"+name);
}
public void showSalary() //第二个成员方法:输出雇员薪水
{
System.out.println("Salary:"+salary);
}
public void showHireDay()//第三个成员方法:输出雇员入职日期
{
System.out.println("HireDay:"+hireDay);
}
public static void main(String args[])//创建mian方法
{
Employee emp = new Employee();//创建雇员类对象
emp.showName(); //调用第一个成员方法showName(),输出雇员姓名
emp.showSalary(); //调用第二个成员方法showSalary(),输出雇员薪水
emp.showHireDay(); //调用第三个成员方法showHireDay(),输出入职日期
}
}
程序运行结果如图所示。
5、参数的传递
同其他编程语言一样,存在方法,就会有参数的传递。方法参数就是方法圆括号类的常量值、变量、表达式、或函数。当定义方法时,此时方法中的参数成为形式参数(形参),是用来反映参数的类型及个数的;当调用该方法时,这时的参数称为实际参数(实参)。通过参数的传递,可以将变量的值传递给方法内部进行处理,需要注意的是,Java中传递的参数共有两种。
(1)基本类型参数:参数都是基本数据类型,包括数值型、布尔型等。在这种情况下,所有的参数传递都采用值传递的方式。也就是说,当值传递到方法中时,方法获得的只是该参数值的一个复制。因此,方法不会改变参数变量的值,只会使用该变量的值。
使用基本类型参数的传递,会发现,方法调用后并不会改变该变量的值,而只是使用了该变量的值
public class ParamEx {
public static void add(int a, int b)//自定义方法,实现加法运算
{
int c = a+b;//自定义变量c,其值等于参数a+b的值
System.out.println("c="+c); //输出c的值
a=c;//将变量c的值赋给a
}
public static void main(String argv[])
{
//定义并初始化变量a、b
int a = 10;
int b = 20;
//调用add()方法
add(a,b);
System.out.println("a="+a);
}
}
(2)对象引用型参数:如果参数传递的是对象引用型参数(即一个对象),则方法中获取的是该对象的内存地址,因此方法可以改变对象中的属性,但是不能改变对象本身。
对象引用型参数的传递:ParamEx2.java
public class ParamEx2 {
//自定义方法用来改变参数
public static void change(String str, char ch[])
{
str = "Change";
ch[0] = 'c';//将字符'c'赋值给字符数组的第一个元素
}
public static void main(String argv[])
{
//创建并初始化字符串对象,及字符组对象
String s = new String("World");
char ch[] = {'H','e','l','l','o'};
//调用change()方法
change(s,ch);
System.out.println("s = "+s);
System.out.print("ch = ");
for(int i=0;i<ch.length; i++)
System.out.print(ch[i]);
}
}
解释:我们可以看到输出的是”cello”,而不是’’Hello”,这说明参数被自定义方法改变了。
6、方法的返回值
在定义每一个方法时,都会定义该方法的返回值类型。这个类型是方法本身的一个结果类型。如果返回值类型为“void”,则说明该方法不返回值,只是执行了一些操作。如果有返回值类型,该类型可以是任何基本类型或对象类型,这时也就可以把这个方法看作一个复杂的变量。但需要注意的是,如果方法指定的返回类型不是“void”,那么方法中必须包含一条return语句,返回指定类型的值,否则会造成语法错误。
7、成员方法重载与过载(覆盖)
Java语言提供了两种方式来实现对同一个方法名的复用,分别为方法重载和方法过载。
(1)方法重载:指存在于同一个类中的方法。多个方法拥有同一个名字,每个方法都有一套唯一的、不同于其他同名方法的参数列表。简单地说就是方法相同,参数列表不同;
(2)方法过载:指方法覆盖,是面向对象语言的特性,只是存在于父类和子类之间。当父类中的方法在继承于它的子类中重新获得定义时,如果该方法名、参数、返回值类型均不变,只有方法体发生了变化时,就称子类的方法过载了父类的方法。
方法重载与过载的主要差别如下:
(1)重载的方法间是彼此独立的,可以看作是完全不同的方法,而过载(覆盖)的方法之间是一种取代关系;
(2)重载的方法存在于同一个类中,数量没有限制,而过载的方法是存在于子类和父类之间的,子类最多包含一个过载方法;
(3)重载的方法必须含有不同的参数列表,而过载的方法必须具有相同的参数列表;
(4)重载的方法返回值类型是任意的,而过载的方法必须具有相同的返回值类型。
下列代码实现了两个重载的方法个,方法名相同但参数列表不同,属于两个不同的方法。
方法重载示例:OverLoad.java
public class OverLoad {
//声并初始化变量
int a = 10;
int b = 20;
int c = 30;
public OverLoad() //构造方法
{
//调用add(int x, int y)方法
System.out.println("a+b="+add(a,b));
//调用add(int x,int y,int z)方法
System.out.println("a+b+c="+add(a,b,c));
}
//自定义第一个方法,实现两个数相加,并将结果返回
public int add(int x,int y)
{return x+y;}
//自定义第二个方法,实现三个数相加,并将结果返回
public int add(int x,int y, int z)
{return x+y+z;}
//创建main()方法
public static void main(String args[])
{
new OverLoad();
}
}
OverLoad程序运行结果
8、static静态成员
static关键字可用来修饰成员变量、方法以及代码段块。使用static修饰的变量、方法都被称为静态成员。静态成员附属于类本身,而不属于类的实例对象。 (1)静态成员变量
一个被修饰为static的成员变量称为静态成员变量。该变量是属于类的,也就是说该变量从类被创建好后便一直存在,其生命周期与其所在类相同。如果一个类有多个实例对象,那么这些实例对象都会共用该静态成员变量。同时在类不创建实例对象的情况下,同样可以通过类名来访问该静态成员变量的值。
静态成员变量示例:StaticMem.java
public class StaticMem
{
static int num = 10;//定义并初始化静态成员变量
public static void main(String argv[])
{
//使用"类名.静态成员变量"的方式来访问
System.out.println(StaticMem.num);
}
}
(2)静态方法
一个被static修饰过的方法,称之为静态方法。这种方法同静态成员变量一样,是属于类的。也就是说该方法从类被创建好之后便一直存在,其生命周期与其所在的类相同。使用静态方法,可以在不创建类对象的情况下,直接使用类名来调用类中的静态方法,为编程带来了极大的灵活性。但要注意的是,静态方法中不能直接访问非静态的成员变量。
任务:在类中定义静态方法,同时在不创建类对象的情况下,直接调用类中的静态方法。
静态方法示例:StaticFun.java
public class StaticFun
{
//定义静态方法
public static void showString()
{
System.out.println("This is a static method");
}
//创建main()方法
public static void main(String[] args)
{
//使用类名直接调用静态方法showString()
StaticFun.showString();
}
}
9、final关键字
final关键字可以用于类、变量、方法前,用来表示该关键字所修饰的类、变量、方法具有不可变的特性。具体情况如下:
(1)final关键字用于数据类型前:被final关键字修饰的是一个常量,在定义后,该变量的值就不能再被改变,同时在定义时就必须被初始化,否则在编译时就会产生错误;
(2)final关键字用于方法声明前:被final关键字修饰的方法被称为最终方法,该方法只能被调用,不能被覆盖,但可以被重载;
(3)final关键字用于类名前:被final关键字修饰的类被称为最终类,该类不能被继承。
任务:使用final关键字定义一个双精度型常量,表示圆周率,从而根据main()方法输入的参数作为半径数值,计算圆的周长和面积。
final关键字使用示例:FinalEx.java
public class FinalEx
{
static final double pie = 3.14;
public static void circularityArea(String r)
{
//类型转换:将字符串转换为双精度变量
double radius = Double.valueOf(r).doubleValue();
//计算圆面积并输出
System.out.println("The circularity's area is:");
System.out.println(pie*radius*radius);
}
public static void circularityPerimeter(String r)
{
//类型转换:将字符串转换为双精度变量
double radius = Double.valueOf(r).doubleValue();
//计算圆周长并输出
System.out.println("The circularity's perimeter is:");
System.out.println(pie*radius*2);
}
public static void main(String[] args)
{
if(args.length!=1)
{
System.out.print("Error!");
System.exit(0);
}
//输出圆的半径
System.out.println("The circularity's radius is:"+args[0]);
//调用计算圆面积的方法
circularityArea(args[0]);
//调用计算圆周长的方法
circularityPerimeter(args[0]);
}
}