1.类的定义:
类用于描述同种对象所拥有的属性和能完成的行为操作,定义一个类之后,就可以用他来创建对象,一般来说,某个对象是属于某个类的对象。
Java中的类有两部分:一部分是系统定义的类,一部分是用户自己定义的类。
2.对象的创建和引用
类本身只是对象的类型,是一个创建对象的模板,如果要表示具体的实体或概念,必须声明和创建对象,由类创建对象的过程也称为类的实例化,创建的对象称为类的一个实例
声明对象变量的一般形式为:
类名 对象变量名; 例如 Farmer farmer;
对象变量是一个引用型的变量,对象变量和基本数据类型的变量有所不同,对象变量中存放的不是对象本身,而是对象的引用;
对象变量经过上面的声明之后,还没有与任何对象联系起来,要真正创建对象还要用new关键词:
类名 对象变量名=new 类名(); 例如farmer = new Farmer();
这样创建完成后,就可以用点操作符类访问对象的成员变量和方法了,格式为:
对象名.成员变量名(或方法名);
实际上Farmer farmer=new Farmer();
这个语句有三个过程
3.构造方法和对象初始化:
构造方法是创建对象时调用的特殊方法,用于完成创建对象所需的初始化工作。构造方法有如下特点:
- 1.构造方法的名字与包含他的类名相同;
- 2.构造方法没有返回值,也不能使用void修饰符;
- 3.构造方法在创建对象的时候用new来调用,一般不能显式调用;
Java中创建对象必须调用构造方法,如果一个类没有定义构造方法,则系统会给他自动生成一个默认的构造方法,默认的构造方法参数表为空,方法体中也没有语句,例如
public class Farmer {
//成员变量
String id;
int years;
int salary;
String skill;
//成员方法
public void work()
{
System.out.printf("工号"+id+"正在工作");
}
public static void main(String[] args)
{
Farmer farmer;//创建一个Farmer类的对象引用farmer
farmer=new Farmer();
//这个Farmer类是没有定义构造函数的,所以java自动给补上去的是无参数的构造函数
farmer.id="F001";//点操作符操作成员变量
farmer.salary=5000;
farmer.work(); //点操作符操作成员函数
}
}
加上构造方法之后例如:
public class Farmer1 {
String id;
int years;
int salary;
String skill;
//自己写构造方法
public Farmer1(String a,int b,int c,String d)
{
id=a;
years=b;
salary=c;
skill=d;
}//注意构造方法没有返回值,也不用void修饰符,构造方法名也要是和类一样的名字
public void work()
{
System.out.printf("工号"+id+"正在工作中");
}
public static void main(String[] args)
{
Farmer1 farmer=new Farmer1("F002",5,5000,"苹果种植");
//初始化这个Farmer1类的对象farmer就要用他的构造方法,因为有自己写的构造方法,要按照参数进行初始化
farmer.work();
}
}
上面的构造方法是有4个参数的,如果在实例化对象的过程中直接调用new Farmer()是会报错的,原因是在自己已经写了有参数的构造方法之后,编译器就不会再提供无参数的构造方法了,但是这种情况下,也可以自己再写一个无参数的构造方法和有参数的构造方法同时存在,并且编译器会默认去调用这个无参数的方法,在此基础上可以对成员变量进行初始化;这个例子改过之后例如:
public class Farmer3 {
String id;
int years;
int salary;
String skill;
public Farmer3()
{
years=1;
salary=2000;
}//这个构造方法无参数,直接给成员变量进行赋值了
public Farmer3(String a,int b,int c,String d)
{
id=a;
years=b;
salary=c;
skill=d;
}//这个构造方法有参数,注意他和上面的无参数方法是同名的
public void work()
{
System.out.printf("工号"+id+"正在工作中……");
}
public static void main(String[] args)
{
Farmer3 farmer=new Farmer3();
//这时候默认调用的无参数的成员方法,括号里无参数
farmer.id="F003";//普通成员变量的访问和赋值
farmer.work();//普通成员方法的调用
}
}
4.方法的重载
一个类中是可以定义多个同名的方法的,只要这些个方法的参数表即可,这个过程称为方法的重载,不同的参数表指的是参数个数、类型或者参数类型的顺序不同,(上一个例子中的两个构造方法的名字就一样)
有了重载,相关的方法就不用费尽心力去其不一样的名字,而是用一样的名字,在调用的时候根据参数来选择。
比如接上例,对于skill变量,方法对他的操作如果在面向不同的实例的时候,对应的skill应该是数量不一样的,因此可以对他的操作情况进行重载,比如下面的更改:
public class Farmer4 {
String id;
int years;
int salary;
String skill;
//成员变量,没有构造方法
public void setSkill(String a)
{
skill=a;
}//setSkill方法,只有一个参数
public void setSkill(String a,String b)
{
skill=a+","+b;
}//重载,参数是两个
public void setSkill(String a,String b,String c)
{
skill=a+","+b+","+c;
}//重载,参数有三个
public void work()
{
System.out.printf("工号"+id+"正在工作中,学习技能是"+skill);
}
public static void main(String[] args)
{
Farmer4 farmer=new Farmer4();//这里的构造函数也是Java自动补上去的
farmer.id="F004";
//farmer.setSkill("苹果种植");
//farmer.setSkill("苹果种植", "桔子种植");
farmer.setSkill("苹果种植", "桔子种植", "梨种植");
farmer.work();
}
}
5.this关键字
一个类的内部,构造方法相互调用是不能用前面例子中的方法的,要用到this关键字,对上面的例子进行改进,如果在实例化的过程中传递参数,则调用有参的构造方法,如果在实例化时没有参数传递,则调用无参构造方法,而无参构造方法里可以加上this()在调用有参的构造方法从而对变量进行赋值:例如
public class Farmer5 {
String id;
int salary;
int year;
String skill;
public Farmer5()
{
this("F005",1,5000,"苹果种植");
//无参数构造方法,但是用this调用了同一个类下面的有参数的构造方法
}
public Farmer5(String a,int b,int c,String d)
{
id=a;
year=b;
salary=c;
skill=d;
}
public void work()
{
System.out.printf("工号"+id+"正在工作中……");
}
public static void main(String[] args)
{
Farmer5 farmer=new Farmer5();
//这里虽然调用的是无参构造方法,但那个无参构造方法本身用this调用了有参的构造方法,也赋值成功了
farmer.work();
}
}
this也可以引用成员变量,因为如果是方法内部的参数,会只是局部变量,不能正确赋值,加上this.之后就可以和成员变量起一样的名字而用前缀进行区分,例如
public class Farmer6
{
String id;
int years;
int salary;
String skill;
public Farmer6(String id,int years,int salary,String skill)
//参数名和这个类的成员变量名一样,容易看懂含义
{
this.id=id;
this.years=years;
this.salary=salary;
this.skill=skill;
}//等号左边为成员变量,右边为构造方法的参数,用this关键字之后不会产生问题,且区分很明显
public void work()
{
System.out.printf("工号"+id+"正在工作中……");
}
public static void main(String[] args)
{
Farmer6 farmer =new Farmer6("F006",1,3000,"苹果种植");
farmer.work();
}
}