------ android培训、java培训、期待与您交流! ----------
“万物皆对象”是Java编程的核心思想,Java语言将对象视为奇特的变量,它可以存储数据,除此之外,你还可以要求它在自身上执行操作。用木匠打一个比方,一个“面向对象的”木匠始终关注的是所制作的椅子,第二位才是所使用的工具,面向对象编程思想的优势在于:①将复杂的事情简单化;②面向对象将以前的过程中的执行者,变成了指挥者;③面向对象这种思想是符合现在人们思考习惯的一种思想。
一、类与对象的区分
类(class)是对具有共性事物的抽象描述,是构造对象的模板或蓝图,是在概念上的一个定义,类也是Java程序的基本单位,那么如何发现类呢?
通常根据名词(概念)来发现类,如在成绩管理系统中:学生、班级、课程、成绩等。
类 对象
学生—张三
班级—622
课程—J2SE
成绩—张三成绩
以上“学生”、“班级”、“课程”、“成绩”等是对象,他们是抽象出来的,称为类;而“张三”、“622”、“J2SE”和“张三的成绩”他们是具体存在的,称为对象,也叫实例(istance),也就是说一个类的具体化(实例化),就是对象或实例。
类与对象关系总结如下:①类=属性+方法,属性来源于类的状态,而方法来源于动作;②每个对象都拥有其类型,每个对象都是某个类的一个实例;③面向对象设计语言使程序员不会受限于任何特定类型的问题,程序可以通过添加新类型的对象使自身适用于某个问题。
二、类的定义
Java中定义类的具体格式:
修饰限定符 class 类名 extends 父对象名称 implements 接口名称 {
类体:属性和方法组成
}
public class Student {
//学号
int id;
//姓名
String name;
//性别
boolean sex;
//地址
String address;
//年龄
int age;
}
以上属性称为成员变量,成员变量和局部变量的区别如下:
①成员变量直接定义在类中,局部变量定义在方法中,参数上,语句中;②成员变量在这个类中有效,局部变量只在自己所属的大括号内有效,大括号结束,局部变量失去作用域;③成员变量存在于堆内存中,随着对象的产生而存在、消失而消失,局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放;④局部变量使用前必须初始化,否则程序编译时会报错,而成员变量会默认初始化,初始化的值名为该类型的默认值。具体的默认值如下:
类型 | 默认值 |
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
char | ‘\u0000’ |
float | 0.0f |
double | 0.0d |
boolean | false |
引用类型 | null |
三、对象的创建和引用
Java中使用new 关键字来创建对象,使用引用(reference)来操作对象。
public class OOTest01 {
public static void main(String[] args) {
//创建一个对象
Student zhangsan = new Student();
System.out.println("id=" + zhangsan.id);
System.out.println("name=" + zhangsan.name);
System.out.println("sex=" + zhangsan.sex);
System.out.println("address=" + zhangsan.address);
System.out.println("age=" + zhangsan.age);
}
}
class Student {
//学号
int id;
//姓名
String name;
//性别
boolean sex;
//地址
String address;
//年龄
int age;
}
对成员变量进行赋值
public class OOTest02 {
public static void main(String[] args) {
//创建一个对象
Student zhangsan = new Student();
zhangsan.id = 1001;
zhangsan.name = "张三";
zhangsan.sex = true;
zhangsan.address = "北京";
zhangsan.age = 20;
System.out.println("id=" + zhangsan.id);
System.out.println("name=" + zhangsan.name);
System.out.println("sex=" + zhangsan.sex);
System.out.println("address=" + zhangsan.address);
System.out.println("age=" + zhangsan.age);
}
}
class Student {
//学号
int id;
//姓名
String name;
//性别
boolean sex;
//地址
String address;
//年龄
int age;
}
一个类可以创建N 个对象,成员变量只属于当前的对象(只属于对象,不属于类),只有通过对象才可以访问成员变量,通过类不能直接访问成员变量
四、匿名对象的特点
匿名对象可以通俗理解为没有名字的对象,匿名对象使用场景:
1:当对方法只进行一次调用的时候,可以使用匿名对象;
2:当对象对成员进行多次调用时,不能使用匿名对象。必须给对象起名字。
匿名对象调用方法时调用完毕就成了垃圾,等待垃圾回收器回收。
为了进一步理解匿名对象的特点,且看以下两道题:
题1:
class Test {
int num = 3;
public static void main(String[] args) {
Test t = new Test();
t.num = 5;
method(t);
System.out.println(t.num);
}
public static void method(Test t){
t.num = 6;
}
}</span>
题2:
class Test {
int num = 3;
public static void main(String[] args) {
Test t = new Test();
t.num = 5;
method(new Test());
System.out.println(t.num);
}
public static void method(Test t){
t.num = 6;
}
}</span>
题1打印输出的是6,题2打印输出的是5,method(new Test())是创建了一个匿名对象,与Test t 在堆内存中的地址是不同的,因此”System.out.println(t.num);”语句仍然输出的是5。
五、面向对象的封装性
以上程序存在缺点,年龄可以赋值为负数,怎么控制不能赋值为负数?
控制对年龄的修改,年龄只能为大于等于0 并且小于等于120 的值。
public class OOTest03 {
public static void main(String[] args) {
//创建一个对象
Student zhangsan = new Student();
/*
zhangsan.id = 1001;
zhangsan.name = "张三";
zhangsan.sex = true;
zhangsan.address = "北京";
zhangsan.age = 20;
*/
zhangsan.setId(1001);
zhangsan.setName("张三");
zhangsan.setSex(true);
zhangsan.setAddress("北京");
zhangsan.setAge(-20);
System.out.println("id=" + zhangsan.id);
System.out.println("name=" + zhangsan.name);
System.out.println("sex=" + zhangsan.sex);
System.out.println("address=" + zhangsan.address);
System.out.println("age=" + zhangsan.age);
}
}
class Student {
//学号
int id;
//姓名
String name;
//性别
boolean sex;
//地址
String address;
//年龄
int age;
//设置学号
public void setId(int studentId) {
id = studentId;
}
//读取学号
public int getId() {
return id;
}
public void setName(String studentName) {
name = studentName;
}
public String getName() {
return name;
}
public void setSex(boolean studentSex) {
sex = studentSex;
}
public boolean getSex() {
return sex;
}
public void setAddress(String studentAddress) {
address = studentAddress;
}
public String getAddress() {
return address;
}
public void setAge(int studentAge) {
if (studentAge >=0 && studentAge <=120) {
age = studentAge;
}
}
public int getAge() {
return age;
}
}
从上面的示例,采用方法可以控制赋值的过程,加入了对年龄的检查,避免了直接操纵student属性,这就是封装,封装其实就是封装属性,让外界知道这个类的状态越少越好。以上仍然不完善,采用属性仍然可以赋值,如果屏蔽掉属性的赋值,只采用方法赋值,如下:
public class OOTest04 {
public static void main(String[] args) {
//创建一个对象
Student zhangsan = new Student();
zhangsan.id = 1001;
zhangsan.name = "张三";
zhangsan.sex = true;
zhangsan.address = "北京";
zhangsan.age = 20;
/*
zhangsan.setId(1001);
zhangsan.setName("张三");
zhangsan.setSex(true);
zhangsan.setAddress("北京");
zhangsan.setAge(20);
*/
/*
System.out.println("id=" + zhangsan.id);
System.out.println("name=" + zhangsan.name);
System.out.println("sex=" + zhangsan.sex);
System.out.println("address=" + zhangsan.address);
System.out.println("age=" + zhangsan.age);
*/
System.out.println("id=" + zhangsan.getId());
System.out.println("name=" + zhangsan.getName());
System.out.println("sex=" + zhangsan.getSex());
System.out.println("address=" + zhangsan.getAddress());
System.out.println("age=" + zhangsan.getAge());
}
}
class Student {
//学号
private int id;
//姓名
private String name;
//性别
private boolean sex;
//地址
private String address;
//年龄
private int age;
//设置学号
public void setId(int studentId) {
id = studentId;
}
//读取学号
public int getId() {
return id;
}
public void setName(String studentName) {
name = studentName;
}
public String getName() {
return name;
}
public void setSex(boolean studentSex) {
sex = studentSex;
}
public boolean getSex() {
return sex;
}
public void setAddress(String studentAddress) {
address = studentAddress;
}
public String getAddress() {
return address;
}
public void setAge(int studentAge) {
if (studentAge >=0 && studentAge <=120) {
age = studentAge;
}
}
public int getAge() {
return age;
}
}
以上采用private 来声明成员变量,那么此时的成员变量只属于Student,外界无法访问,这样就封装了我们的属性,那么属性只能通过方法访问,通过方法我们就可以控制对内部状态的读取权利。
总结,Java采用封装性的好处主要如下:①将变化隔离;②便于使用;③提高重用性;④增加安全性
六、构造函数(构造方法,构造器,Constructor)
构造方法主要用来创建类的实例化对象,可以完成创建实例化对象的初始化工作,声明格式:
构造方法修饰词列表 类名 (方法参数列表)
构造方法修饰词列表:public、proteced、private
类的构造方法和普通方法一样可以进行重载
构造方法具有的特点:
①构造方法名称必须与类名一致
②构造方法不具有任何返回值类型,即没有返回值,关键字void 也不能加入,加入后就不是构造方法了,就成了普通的方法了
③任何类都有构造方法,如果没有显示的定义,则系统会为该类定义一个默认的构造器,这个构造器不含任何参数,如果显示的定义了构造器,系统就不会创建默认的不含参数的构造器了。
1.默认构造方法(无参构造方法)
public class ConstructorTest01 {
public static void main(String[] args) {
// 创建一个对象
Student zhangsan = new Student();
zhangsan.setId(1001);
zhangsan.setName("张三");
zhangsan.setSex(true);
zhangsan.setAddress("北京");
zhangsan.setAge(20);
System.out.println("id=" + zhangsan.getId());
System.out.println("name=" + zhangsan.getName());
System.out.println("sex=" + zhangsan.getSex());
System.out.println("address=" + zhangsan.getAddress());
System.out.println("age=" + zhangsan.getAge());
}
}
class Student {
// 学号
private int id;
// 姓名
private String name;
// 性别
private boolean sex;
// 地址
private String address;
// 年龄
private int age;
// 默认构造方法
public Student() {
// 在创建对象的时候会执行该构造方法
// 在创建对象的时候,如果需要做些事情,可以放在构造方法中
System.out.println("----------Student-------------");
}
// 设置学号
public void setId(int studentId) {
id = studentId;
}
// 读取学号
public int getId() {
return id;
}
public void setName(String studentName) {
name = studentName;
}
public String getName() {
return name;
}
public void setSex(boolean studentSex) {
sex = studentSex;
}
public boolean getSex() {
return sex;
}
public void setAddress(String studentAddress) {
address = studentAddress;
}
public String getAddress() {
return address;
}
public void setAge(int studentAge) {
if (studentAge >= 0 && studentAge <= 120) {
age = studentAge;
}
}
public int getAge() {
return age;
}
}
2.带参数的构造方法
public class ConstructorTest02 {
public static void main(String[] args) {
// 调用带参数的构造方法对成员变量进行赋值
Student zhangsan = new Student(1001, "张三", true, "北京", 20);
System.out.println("id=" + zhangsan.getId());
System.out.println("name=" + zhangsan.getName());
System.out.println("sex=" + zhangsan.getSex());
System.out.println("address=" + zhangsan.getAddress());
System.out.println("age=" + zhangsan.getAge());
}
}
class Student {
// 学号
private int id;
// 姓名
private String name;
// 性别
private boolean sex;
// 地址
private String address;
// 年龄
private int age;
public Student(int studentId, String studentName, boolean studentSex,
String studentAddress, int studentAge) {
id = studentId;
name = studentName;
sex = studentSex;
address = studentAddress;
age = studentAge;
}
// 设置学号
public void setId(int studentId) {
id = studentId;
}
// 读取学号
public int getId() {
return id;
}
public void setName(String studentName) {
name = studentName;
}
public String getName() {
return name;
}
public void setSex(boolean studentSex) {
sex = studentSex;
}
public boolean getSex() {
return sex;
}
public void setAddress(String studentAddress) {
address = studentAddress;
}
public String getAddress() {
return address;
}
public void setAge(int studentAge) {
if (studentAge >= 0 && studentAge <= 120) {
age = studentAge;
}
}
public int getAge() {
return age;
}
}
需要注意的是,手动建立的构造方法,将会把默认的构造方法覆盖掉。
3.构造代码块和构造函数有什么区别?
构造代码块:是给所有的对象进行初始化,也就是说,所有的对象都会调用一个代码块。只要对象一建立。就会调用这个代码块。
构造函数:是给与之对应的对象进行初始化。它具有针对性。