------ 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.构造代码块和构造函数有什么区别?
构造代码块:是给所有的对象进行初始化,也就是说,所有的对象都会调用一个代码块。只要对象一建立。就会调用这个代码块。
构造函数:是给与之对应的对象进行初始化。它具有针对性。