类与对象
java中定义类时使用class关键字,对象的属性以成员变量的形式存在,对象的方法以成员方法的形式存在,其语法如下:
class 类名称{
//类的成员变量
//类的成员方法
}
1.成员变量
在java中对象的属性也称为成员变量,成员变量的定义与普通变量的定义一样,语法如下:
数据类型 变量名称 【 = 值 】
其中,【 = 值 】表示可选内容,定义变量时可以为其赋值,也可以不为其赋值。
首先定义一个水果(Fruits)类,成员变量对应于类对象的属性,在 Fruits类中设置4个成员变量,分别为Apple、Orange、Banana、Watermelon,分别对应于苹果,橘子,香蕉,西瓜,例如,在项目中创建水果(Fruits)类,在该类中定义成员变量,代码如下:
public class Fruits {
String Apple; //苹果
String Orange; //橘子
String Banana; //香蕉
String Watermelon; //西瓜
}
从以上代码可以看到在java中使用class关键字来定义类,Fruits是类的名称。同时在Fruits类中定义了4个成员变量,成员变量的类型可以设置为java中合法的数据类型,其实成员变量就是普通的变量,可以设置初始值,也可以不设置初始值,如果不设置初始值,则会有默认值。java中常见类型的默认值如下:
数 据 类 型 | 默 认 值 | 说 明 |
---|---|---|
byte、short、int、long | 0 | 整形零 |
float、double | 0.0 | 浮点零 |
char | '' | 空格字符 |
Boolean | false | 逻辑假 |
引用类型,例如String | null | 空值 |
以下代码验证上图中数据类型的默认值:
public class Dpc {
byte _byte;
short _short;
int _int;
long _long;
float _float;
double _double;
char _char;
boolean _boolean;
String _str;
public static void main(String[] args) {
//创建Dpc类
Dpc def = new Dpc();
System.out.println("byte默认值:" + def._byte);
System.out.println("short默认值:" + def._short);
System.out.println("int默认值:" + def._int);
System.out.println("long默认值:" + def._long);
System.out.println("float默认值:" + def._float);
System.out.println("double默认值:" + def._double);
System.out.println("boolean默认值:" + def._boolean);
System.out.println("String默认值:" + def._str);
System.out.println("char默认值:" + def._char);
}
}
返回结果:
byte默认值:0
short默认值:0
int默认值:0
long默认值:0
float默认值:0.0
double默认值:0.0
boolean默认值:false
String默认值:null
char默认值:[ ]
2.成员方法
在java语言中,成员方法对应于类对象的行为,它主要来定义类可执行的操作,它是包含一系列语句的代码块。
定义成员方法的语法格式如下:
【权限修饰符】【返回值类型】方法名(【参数类型 参数名】)【throws 异常类型】{
........//方法体
return 返回值;
}
- 权限修饰符:
- 可以是private、public、protected中的任意一个,也可以不写,主要用来控制方法的访问权限;
- 返回值类型:
- 用来指定方法返回数据的类型,可以是任何类型,如果方法不需要返回值,则使用void关键;
- 方法:
- 一个成员方法既可以有参数,也可以没有参数,参数可以是对象,也可以是基本数据类型的变量;
例如,定义一个Dpc()方法,用来输出Hello World,代码如下:
public void Dpc() {
System.out.println("Hello World");
}
方法的定义必须在某个类中,定义方法时如果没有指定权限修饰符,方法的默认访问权限为缺省(即只能在本类及同一个包中的类进行访问)。
如果定义的方法有返回值,则必须使用return关键字返回一个指定类型的数据,并且返回值类型要与方法返回值类型一致,例如,定义一个返回值为int的方法,就必须使用return返回一个int类型的值,代码如下:
public int Dpc() {
System.out.println("Hello World");
return 1;
}
上面代码中,如果将"return 1"删除,会提示报错:方法无返回值的错误提示;
3.成员方法的参数
调用方法时可以给该方法传递一个或多个值,传给方法的值叫作实参,在方法内部,接受实参的变量叫作形参,形参的声明语法与变量的声明语法一样。形参只在方法内部有效。java中方法的参数主要有三种,分别为值参数、引用参数和不定长参数,下面分别进行演示。
- 值参数
值参数表明实参与形参之间按值传递,当使用值参数的方法被调用时,编译器为形参分配存储单元,然后将对于的实参的值复制到形参中,由于是值类型的传递方式,所以,在方法中对值类型的形参的修改并不会影响实参。
使用传递参数计算整数相加的例子,代码如下:
public class Dpc {
int sum;
public void sum(int num1,int num2) {
//计算传过来的参数的值赋予sum变量
sum = num1 + num2;
System.out.println("计算" + num1 + "+" + num2 + "等于几:" + sum);
}
public static void main(String[] args) {
Dpc a = new Dpc();
//传递整数类型1和2,分别为num1和num2的值
a.sum(1,2);
}
}
返回结果:
计算1+2等于几:3
- 引用参数:
如果在给方法传递参数时,参数的类型是数组或者其他引用类型,那么,在方法中对参数的修改会反映到原有的数组或者其他引用类型上,这种类型的方法参数被称之为引用参数。
下面以一个整数类型的数组为例,把原数组的值都加1,代码如下:
public class Dpc {
public static void main(String[] args) {
int num[] = {10, 20, 30, 40, 50};
System.out.print("原值为:");
//---------遍历数组原值------------
for (int i = 0; i < num.length; i++) {
System.out.print(num[i] + " ");
}
System.out.println();
System.out.print("修改后的值为:");
//创建类
Dpc a = new Dpc();
//传递数组参数
a.sum(num);
//遍历计算之后的新数组
for (int i = 0; i < num.length; i++) {
System.out.print(num[i] + " ");
}
}
public void sum(int[] i) {
for(int j=0;j<i.length;j++) {
//计算数组并从新赋值
i[j] = i[j] + 1;
}
}
}
返回结果:
原值为:10 20 30 40 50
修改后的值为:11 21 31 41 51
在计算值sum方法中,i[j]可以理解为下面这样:
num[0] = num[0] + 1
num[1] = num[1] + 1
.....................以此类推
- 不定长参数
声明方法时,如果有若干个相同类型的参数,可以定义为不定长参数,该类型的参数声明下:
权限修饰符 返回值类型 方法名(参数类型... 参数名)
注意:参数类型和参数之间有三个点,而不是其他数量或者省略号
例如,对1,2,3,4,5,6............这样的整数求和,就可以使用参数为不定长参数的成员方法,以成员方法add(int...x)为例,代码如下:
public class Dpc {
//定义方法,并指定不定长参数的类型为int
int add(int... x) {
//计算结果
int result = 0;
//遍历
for (int i = 0; i < x.length; i++) {
//数值相加
result += x[i];
}
System.out.println(result);
//返回运算结果
return result;
}
public static void main(String[] args) {
Dpc a = new Dpc();
//传入方法参数
a.add(1,2,3,4,5,6);
}
}
返回结果:
21
4.构造方法
在类中除了成员方法之外,还存在一种特殊类型的方法,那就是构造的方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造放。
构造方法的特点如下:
- 构造方法没有返回类型,也不能定义为void;
- 构造方法的名称要与本类的名称相同;
- 构造方法的主要作用是完成对象的初始化工作,他能把定义对象的参数传给对象成员;
构造方法的定义语法如下:
public class Dpc {
public Dpc(){
}
}
- public:构造方法的修饰符
- Dpc:构造方法的名称
在构造方法中 可以为成员变量赋值,这样当实例化一个本类的对象时,相应的成员变量也将被初始化,如果类中没有明确定义构造的方法,则编译器会自动创建一个不带参数的默认构造方法。
除此之外,在类中定义构造方法时,还可以为其添加一个或者多个参数,即有参构造方法,语法如下:
public class Dpc {
String str;
public Dpc(String str1){
//对成员变量初始化
}
public static void main(String[] args) {
//创建类并向构造方法传递字符串类型的参数
Dpc a = new Dpc("你好");
}
}
无参数构造方法可以不用传递参数,语法如下:
public class Dpc {
String str;
//无参数构造方法
public Dpc(){
//对成员变量初始化
str = "你好";
}
public static void main(String[] args) {
//创建Dpc类
Dpc a = new Dpc();
}
}
注意:如果在类中定义的构造方法都是有参构造方法,则编译器不会为类自动生成一个默认的无参构造方法,当试图调用无参构造方法实例化一个对象时,编译器会报错。
5.局部变量
如果在成员方法内定义一个变量,那么这个变量被称为局部变量。
局部变量在方法执行时被创建,在方法执行借宿时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。
局部变量的作用域,即局部变量的有效范围,如下图:
如果i变量写在作用域之外编译器就会报错:
在互相不嵌套的作用域中可以同时声明两个名称和类型相同的局部变量,如下图:
但是在相互嵌套的区域中不可以这样声明,如果将局部变量id在方法体的for循环中再次定义,编译器将会报错,如下图:
5.this关键字
当类中的成员变量与成员方法中的参数重名时,方法中如何使用成员变量呢?首先来看一下重名的情况下回发生什么问题。
例如,创建一个类,定义一个成员变量name并赋初值,在定义一个成员方法str(String name),输出方法中name的值,代码如下:
public class Dpc {
String name = "456";
public void str(String name) {
System.out.println(name);
}
public static void main(String[] args) {
Dpc a = new Dpc();
a.str("123");
}
}
看一下返回结果:
123
从这个结果可以看出,输出的值不是成员变量的值,也就是说,如果方法中出现了与局部变量同名的参数,会导致方法无法直接使用成员变量。
在上述代码中可以看到,成员变量与在str()方法中的形式参数的名称相同,都为name,那么如何在类中区分使用的是哪一个变量呢?在java语言中规定使用this关键字来代表本类对象的引用,this关键字被隐式地用于引用对象的成员变量方法。
以下代码是使用this关键字的用法:
public class Dpc {
String name = "《西游记》";
public void book(String name) {
//使用this关键字重新定义成员变量name的值
this.name = name;
System.out.println(name);
}
public static void main(String[] args) {
Dpc a = new Dpc();
a.book("《红楼梦》");
}
}
返回结果:
《红楼梦》
事实上,this关键字引用的就是本类的一个对象,在局部变量或方法参数覆盖了成员变量时,如上面代码的情况,就要添加this关键字明确引用的是类成员还是局部变量或方法参数。
如果省略this关键字直接写成name=name,那只是把参数name赋值给参数变量本身而已,成员变量name的值没有改变,因为参数name在方法的作用域中覆盖了成员变量name。
this关键字可以调用类的成员变量和成员方法,此外,它还可以调用类中的构造方法。
下面以一个用户密码为例,如果用户不填密码则默认密码为123456,先创建有参数和无参数构造方法,无参构造方法调用有参数构造方法并实现初始化,代码如下:
public class Dpc {
int passwd;
//有参数构造方法,参数为用户输入的密码
public Dpc(int passwd) {
this.passwd = passwd;
System.out.println("您的密码为:" + passwd);
}
//无参数构造方法使用默认密码
public Dpc() {
//调用有参数构造方法
this(123456);
}
public static void main(String[] args) {
//创建Scanner类,在控制台输出
Scanner sc = new Scanner(System.in);
System.out.print("是否使用默认密码(Y/N):");
//将输入的Y和N赋值给state变量
String state = sc.next();
if(state.equals("N")) {
System.out.print("请输入密码:");
//控制台输入的密码赋值给整数类型的new_passwd变量
int new_passwd = sc.nextInt();
//调用有参数构造方法
Dpc a = new Dpc(new_passwd);
}else if(state.equals("Y")) {
//调用无参数构造方法
Dpc b = new Dpc();
}
}
}
返回结果如下图:
6.static关键字
由static修饰的变量、常量和方法分别被称作静态变量、静态常量和静态方法,也被称作类的静态成员。
-
静态变量
很多时候,不同的类之间需要对同一个变量进行操作,比如一个水池,同时打开入水口和出水口,出水和进水这两个动作会同时影响到水池 中的水量,此时水池中的水量就可以认为是一个共享的变量。
在java中,如果把共享的变量用static修饰,那么该变量就是静态变量,调用静态变量语法如下:
类名.静态类成员
- 静态方法
如果想要使用类中的成员方法,需要先将这个类进行实例化,但有些时候不想或者无法创建类的对象时,还要调用类中的方法才能够完成业务逻辑,这样情况下就可以使用静态方法。
调用类的静态方法如下:
类名.静态方法()
创建一个水池类,使用静态变量表示水池中的水量,并初始化水池中的水量为0,通过调用静态方法之注水方法(一次注入3个单位)和放水方法(一次放出2个单位),控制水池中的水量,代码如下:
public class Dpc {
//初始化静态变量之水池中的水量为0
public static int water = 0;
//创建放水静态方法,一次放出2个单位
public static void outlet() {
if (water >= 2) {
water = water - 2;
}else {
water = 0;
}
}
//创建注水方法,一次注入3个单位
public static void inlet() {
water = water + 3;
}
public static void main(String[] args) {
System.out.println("水池的水量:" + Dpc.water);
System.out.println("水池注水两次");
Dpc.inlet();
Dpc.inlet();
System.out.println("水池的水量:" + Dpc.water);
System.out.println("水池放水一次");
Dpc.outlet();
System.out.println("水池的水量:" + Dpc.water);
}
}
返回结果:
水池的水量:0
水池注水两次
水池的水量:6
水池放水一次
水池的水量:4
7.静态代码块
在类的成员方法之外,用static修饰代码区域可以称之为静态代码块,定义一块静态代码块,可以完成类的初始化操作,在类声明时就会运行,语法如下:
public class Dpc {
static {
//此处编辑执行语句
}
}
创建静态代码块、非静态代码块、构造方法、成员方法,查看这几处代码的调用顺序,代码如下:
public class Dpc {
static String name;
// 静态代码块
static {
System.out.println(name + "静态代码块");
}
// 非静态代码块
{
System.out.println(name + "非静态代码块");
}
public Dpc(String a) {
name = a;
System.out.println(name + "构造方法");
}
public void method() {
System.out.println(name + "成员方法");
}
public static void main(String[] args) {
Dpc s1;// 声明的时候就已经运行静态代码块了
Dpc s2 = new Dpc("s2");// new的时候才会运行构造方法
Dpc s3 = new Dpc("s3");
s3.method();// 只有调用的时候才会运行
}
}
返回结果:
null静态代码块
null非静态代码块
s2构造方法
s2非静态代码块
s3构造方法
s3成员方法
从返回结果可以看出:
- 静态代码块由始至终只运行一次;
- 非静态代码块,每次创建对象的时候,会在构造方法之前运行。所以读取成员变量name时,只能获取到String类型的默认值null;
- 构造方法只有在使用new创建对象的时候才会运行;
- 成员方法只有在使用对象调用的时候才会运行;
- 因为name时static修饰的静态成员变量,在创建s2对象时将字符串s2赋给了name,所以创建s3对象时,重新调用了类的非静态代码块,此时name的值还没有被s3对象改变,于是就会输出s2非静态代码块了;
8.类的主方法
主方法是类的入口点,他指定了程序如何开始,提供对程序流向的控制,java编辑器通过主方法来执行程序。
主方法的语法如下:
public static void main(String[] args) {
//主方法体
}
}
在主方法的定义中可以看到主方法具有以下特性:
- 主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的;
- 主方法没有返回值;
- 主方法的形参为数组。其中args[0]~args[n]分别代表程序的第一个参数到第n+1个参数,可以使用args.length获取参数个数;
在项目中创建个类,在主方法中编写以下代码,并在Eclipse编译器中设置程序参数,代码如下:
public class Dpc {
//定义主方法
public static void main(String[] args) {
//遍历参数
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);;
}
}
}
在Eclipse中设置程序参数的步骤如下图:
返回结果:
参数1
参数2
参数3