Java类的概念
我们不能将一个事物称之为一类事物,例如一只鸟我们不能称为鸟类,但是我们需要给一类事物统称,例如大雁,麻雀,燕子,统称为鸟类,在Java中我们对这种统称需要用到类的概念。
类是同一类事物的统称,将现实世界的一个事物抽象成对象,类就是这类事物的统称,如鸟类,人类,家禽类。类是构造对象时所依赖的规范。一只鸟会有一对翅膀,他可以用这对翅膀进行飞行,基本上所有的鸟类都有“有翅膀”这个特性和用这对翅膀飞行的功能,这样的具有相同特性和行为的一类事物就称为类,类的思想就是这样的。
类是封装对象的属性和行为的载体,在Java语言中,类对象的行为是以方法的形式定义的,对象的属性是以成员变量的形式定义的,所以类包括对象的属性和方法。
一、成员变量
在Java中,对象的属性也称为成员变量,成员变量可以是任意类型,成员变量的作用域是整个类。
public calss Book{ //定义一个书类
private String name; //定义String类型的成员变量
public String getName(){ //成员变量name的get方法
return name;
}
public void setName(String name){ //成员变量name的set方法
this.name = name; //将参数值赋给成员变量name
}
}
上面创建的是一个Book类,在类中设置了一个name属性,并编写了该属性的Getter/Setter方法。
在Java语言中定义类需要使用class关键字,Book是类的名称,在Book类中定义了一个成员变量,成员变量的类型为String类型。成员变量其实就是一个普通的变量,可以为它设置初始值,也可以不设置初始值,如果不设置初始值,那么会有默认的初始值。
二、成员方法
在Java中,使用成员方法对应于类对象的行为,以上面的Book类为例,它包含了getName()和setName()两个方法,这两个成员方法分别为获取图书名称和设置图书名称的方法。
定义成员方法的语法格式如下:
权限修饰符 返回值类型 方法名(参数类型 参数名){
…… //方法体
return 返回值;
}
一个成员方法可以有参数,这个参数可以是对象,也可以是基本数据类型的变量,同时成员方法有返回值和不返回任何值的选择,如果方法需要返回值,可以使用return关键字来返回值,使用这个关键字,方法执行到这句语句的时候,方法将被中止。(如果想要使成员方法无返回值,可以使用void关键字表示)。
成员方法的返回值可以是计算结果,也可以是其它想要的数值和对象,返回值的类型要与方法返回值类型一致。
在成员方法中可以调用其他成员方法和类成员变量,在成员方法中也可以定义一个变量,但是方法中定义的变量为局部变量。
成员方法和成员变量统称为类成员。
三、权限修饰符
Java中的权限修饰符主要包括private、public和protected,这些修饰符控制着对类和类的成员变量以及成员方法的访问。
private修饰符如果修饰成员变量和成员方法,则该成员只能在本类中使用,在子类中是不可见的,对其他包的类也是不可见的。
private修饰类时,这个类将隐藏其中所有的数据,防止用户直接访问该类。
public修饰符修饰成员变量和成员方法时,那么除了可以在本类访问使用这些数据,还可以在子类和其他包的类中使用。
public 修饰类的时候,类中的数据可以被子类和其他包的类访问。
protected修饰类的时候,只有本包内的该类的子类和其他类可以访问该类中的成员变量和成员方法。
综上所述:
public 和 protected修饰的类可以由子类进行访问,如果子类和父类不在同一个包下,那么只能使用public 修饰才能保证该类可以被子类进行访问。如果父类不希望通过继承产生的子类访问他的成员变量,则需要使用private修饰它的成员变量。
访问位置 | private | protected | public |
本类 | 可访问 | 可访问 | 可访问 |
同包其他类或子类 | 不可访问 | 可访问 | 可访问 |
其他包的类或子类 | 不可访问 | 不可访问 | 可访问 |
当声明类的时候不适用权限修饰符不设置类的权限,则这个类预设为包存取范围,即只有一个包中的类可以访问这个类中的成员变量和成员方法。
例如:在项目com.mr下创建AnyClass类,该类使用默认不写权限修饰符。
package com.cr;
calss AnyClass{
public void doString(){
…… //方法体
}
}
上述代码中类AnyClass的修饰符为默认修饰符,即只有一个包内的其他类和子类可以对该类进行访问,而在这个类中doString()方法却使用了public修饰,即使这样,doString()方法访问权限依然和类AnyClass相同。
四、局部变量
如果在成员方法中定义一个变量,该变量就是一个局部变量,方法的形参也是一个局部变量,局部变量在方法被执行时创建,在方法执行结束时被回收。局部变量在使用时必须先进行赋值操作或初始化,否则会出现编译错误。
例如:编写程序交换两个整数的值。
定义一个类DemoArray,在该类中定义change()方法,该方法参数为一个整型数组,将数组前两个元素值互换,通过在方法中定义一个保存临时数据的局部变量temp,利用temp交换两个元素的值。
public class DemoArray{
public static void main(String[] args){
int[] array = {10,20};
System.out.println("原数组中第一个值是:" + array[0] + ",第二个值是:" + array[1]);
array = change(array);
System.out.println("交换后数组中第一个值是:" + array[0] + ",第二个值是:" + array[1]);
}
public static int[] change(int[] array){
int temp = array[0];
array[0] = array[1];
array[1] = temp;
return array;
}
}
程序运行结果如下:
原数组中第一个值是:10,第二个值是:20
交换后数组中第一个值是:20,第二个值是:10
局部变量的有效范围称为变量的作用域,局部变量的有效范围从该变量的声明开始到该变量的结束为止。在不嵌套的两个作用域中,可以定义同名的局部变量。但是在嵌套的作用域内不可以定义同名变量。
五、this关键字
this关键字用于表示本类当前的对象,这个当前对象不是某个new出来的实体对象,而是当前正在编辑的类。this关键字只能在本类中使用。
例如上面的Book类中setName()方法代码如下:
public void setName(String name){ //定义一个setName()方法
this.name = name; //将参数赋给类中的成员变量
}
上述代码中,我们故意将参数名称设置的和成员变量名一样都是name,区分使用的是哪一个变量时就要用到this关键字,在Java中规定用this关键字代表本类对象的引用,this关键字用于引用对象的成员变量和成员方法。上述代码中this.name中的name指的就是Book类中的成员变量name,而this.name = name的第二个name指的就是形参中的name,这条语句的意思就是将形参name的值赋给成员变量name。在Java语言中最常规的调用方式就是使用“对象.成员方法”或者“对象.成员变量”进行调用。this引用的就是本类的一个对象,当局部变量覆盖了成员变量的时候,像上面的name一样,出现了重名的情况就要添加this关键字明确引用的是类成员还是局部变量。如果省略this关键字直接写成name = name那么表达的意思就是将参数name赋值给参数变量本身而已,成员变量name的值并没有改变,因为参数name在作用域中覆盖了成员变量name。
this关键字也可以作为方法的返回值,例如返回图书类本类的对象,可以写成如下形式:
public Book getBook(){
return this; //返回Book类的本类对象
}
在getBook()方法中,返回值为Book,所以方法体中使用return this这种形式返回Book类对象。
六、类的构造方法
在类中,除了成员方法之外,还存在一种特殊类型的方法,就是构造方法。构造方法是一个与类同名的方法,对象的创建是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。
构造方法的特点如下:
- 构造方法没有返回值。
- 构造方法的名称要与类名称相同(大小写也要保持一致)。
构造方法没有返回值与普通的没有返回值的写法不一样,普通方法没有返回值要使用void关键字,但是构造方法直接省略返回值。例如一个普通方法没有返回值,那么就定义成下面这种类型public void method()。但是构造方法直接使用public method()即可,不需要使用void。
构造方法的定义语法如下:
public Book(){
…… //构造方法体
}
- public: 构造方法修饰符。
- Book:构造方法的名称。
在构造方法中可以为成员变量赋值,这样当实例化一个本类对象时,相应的成员变量也将被初始化。如果类中没有明确定义构造方法,编译器会自动创建一个不带任何参数的默认无参构造方法。
注意:当类中只要定义了一个构造方法,系统将不再自动创建一个无参构造。如果类中没有定义无参构造,定义了含参构造,这是试图使用无参构造方法实例化一个对象时,编译器会报错。所以只有在类中没有定义任何构造方法时,编译器才会自动创建无参构造,因此我们应该养成一个习惯,定义类时手动提供一个无参构造。
this关键字还可以调用类中的构造方法:
例如:构造鸡蛋灌饼:当顾客购买鸡蛋灌饼时,如果要求加两个鸡蛋,那么店家就给饼加两个鸡蛋;不要求时,店家会默认给饼中加一个蛋。创建鸡蛋灌饼类(EggCake),使用this关键字,在无参构造方法中调用有参构造方法,实现上述加蛋过程。代码如下:
public class EggCake{
int eggCount; //创建成员变量记录饼中的鸡蛋数
public EggCake(int eggCount){ //参数为鸡蛋灌饼里鸡蛋个数的构造方法
this.eggCount = eggCount; //将参数eggCount赋值给属性eggCount
}
public EggCake(){ //无参构造方法,默认加一个蛋
//调用参数为鸡蛋个数的构造方法,并设置鸡蛋个数为1.
this(1);
}
public static void main(String[] args){
EggCake cake1 = new EggCake();
EggCake cake2 = new EggCake(2);
System.out.println("顾客不要求加鸡蛋,饼里会有:" + cake1.eggCount + "个鸡蛋");
System.out.println("顾客要求加鸡蛋,饼里会有:" + cake2.eggCount + "个鸡蛋");
}
}
程序运行结果:
顾客不要求加鸡蛋,饼里会有:1个鸡蛋
顾客要求加鸡蛋,饼里会有:2个鸡蛋
七、静态变量和静态方法
这里我们需要认识一个新的关键字static,被static修饰的变量和方法称为静态变量和静态方法,静态变量和静态方法被称为静态成员,静态成员属于类所有,区别于对象,静态的成员是属于类的所以推荐使用类名加“.”运算符调用,语法如下:
类名.静态类成员
创建并调用静态属性和静态变量:
创建StaticDemo类,在类中使用static关键字定义一个属性和一个方法,并在主方法中调用。
public class StaticDemo{
static double PI = 3.1415; //在类中定义静态变量
public static void method(){ //在类中定义静态方法
System.out.println("这是静态方法");
}
public static void main(String[] args){
System.out.println(StaticDemo.PI); //调用静态变量
StaticDemo.method(); //调用静态方法
}
}
程序运行结果如下:
3.1415
这是静态方法
静态成员也可以通过对象名和"."运算符调用,但是不推荐这么用,因为这样容易混淆静态成员和非静态成员。
静态变量和静态方法通常是为了提供共享数据或方法,静态成员同样遵循权限修饰符的约束。
例如:统计顾客总人数:在Cust类中创建一个静态整数类型属性count,在构造方法中让count自增:
public class Cust{ //定义顾客类
static int count = 0; //共享的属性定义为静态:人数
String name; //名称属性
public Cust(String name){
this.name = name;
count++;
}
public static void main(String[] args){
Cust cust1 = new Cust("张三");
System.out.println("我是第" + Cust.count + "名顾客,我的名字是:" + cust1.name);
Cust cust2 = new Cust("李四");
System.out.println("我是第" + Cust.count + "名顾客,我的名字是:" + cust2.name);
Cust cust3 = new Cust("王五");
System.out.println("我是第" + Cust.count + "名顾客,我的名字是:" + cust3.name);
}
}
程序运行结果为:
我是第1名顾客,我的名字是:张三
我是第2名顾客,我的名字是:李四
我是第3名顾客,我的名字是:王五
从这个结果就可以看出,count是用static修饰的,对于所有顾客类对象来说,这个属性是共用的,并且每创建一个顾客,count这个属性就会加1,所以最后count统计出来的就是顾客的总人数。
如果在执行类时,希望先执行类的初始化动作,可以使用static定义一个静态区域,这块区域被称为静态代码块。当类文件被执行时,会首先执行stati块中的程序,并且只会执行一次。静态代码块的语法如下:
public class example{
static{
…… //这里可以写初始化的代码
}
}
总结一下static关键字要注意的几点:
- 静态方法中不可以使用this关键字。
- 静态方法中不可以直接调用非静态方法。
- 局部变量不可以使用static关键字声明。
- 主方法必须用static声明。
- 只有内部类可以使用static关键字声明。
八、类的主方法
主方法就是类的入口点,它定义了从何处开始,主方法提供对程序流向的控制,java编译器通过主方法来执行程序,主方法的语法如下:
public static void main(String[] args){
…… //方法体
}
在主方法的定义下可以看到其具有以下特性:
- 主方法必须是静态的,所以如果在主方法中定义方法,方法也必须是静态的。
- 主方法没有返回值。
- 主方法形参是一个字符串类型的数组。