深入分析类与对象
1, 成员属性封装
在类之中的组成就是属性与方法, 一般而言方法都是对外提供服务的, 所以是不会进行封装处理的, 而对于属性需要较高的安全性, 所以往往需要对其进行保护, 这个时候就需要采用封装性对属性进行保护.
在默认的情况下, 对于类中的属性是可以通过其他类利用对象进行调用的.
. 范例: 属性封装情况下的问题
- class Person{
- String name;
- int age;
- public void tell(){
- System.out.println("姓名:"+this.name+", 年龄:"+this.age);
- }
- }
- public class Main {
- public static void main(String[] args) {
- Person person1 = new Person();// 声明对象
- person1.name="张三";
- person1.age=18;
- person1.tell();
- }
- }
. 范例: 对属性进行封装此时在 Person 类中提供的 name 与 age 两个属性并没有进行封装处理, 但是有可能所设置的数据是一个错误的数据. 如果想要解决这样的问题就可以利用 private 关键字进行封装处理.
- class Person{
- private String name;
- private int age;
- public void tell(){
- System.out.println("姓名:"+this.name+", 年龄:"+this.age);
- }
- }
.[setter,getter] 设置或取得属性可以使用 setXxx(),getXxx() 方法, 而属性一旦封装之后外部将不能够直接访问, 即: 外部不可见, 但是对类的内部可见, 如果想要外部的程序访问封装的属性, 则在 Java 开发标准中提供有如下要求:
- class Person{
- private String name;
- private int age;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public void tell(){
- System.out.println("姓名:"+this.name+", 年龄:"+this.age);
- }
- }
. 范例: 实现方法
- public class Main {
- public static void main(String[] args) {
- Person person1 = new Person();// 声明对象
- person1.setName("张三");
- person1.setAge(-18);
- person1.tell();
- }
- }
在以后任何类定义的时候一定要记住, 类中的所有属性都必须要使用 private 封装 (98%), 并且属性如果要进行访问必须要提供 setter,getter 方法.
2, 构造方法与匿名对象
现在的程序在使用类的时候一般都按照了如下的步骤进行:
. 声明并且实例化对象, 这个时候实例化对象中的属性并没有任何的数据存在, 都是其对应数据的默认值;
. 需要通过一系列的 setter 的方法进行为类中的属性设置内容.
等于现在想要真正活动一个可以正常使用的实例化对象, 必须经过两个步骤才可以完成.
但是如果按照这样的方式来进行思考的话就会发现一个问题: 假设类中的属性很多个, 那么按照上述方法, 就需要调用很多次 setter 的方法进行内容设置. 这样的调用实在是太啰嗦了. 所以在 Java 里面为了考虑到对象的初始化问题, 专门提供有构造方法, 即: 可以通过构造方法实现实例化对象中的 属性初始化处理, 只有在关键字 new 的时候才使用构造方法.
在 Java 程序里面构造方法的定义要求如下:
. 构造方法名称与类名称保持一致;
. 构造方法不允许设置任何的返回值类型, 即没有返回值定义;
. 构造方法是在使用关键字 new 实例化对象的时候自动调用的.
. 范例: 构造方法
- class Person{
- private String name;
- private int age;
- public Person() {// 无参构造
- }
- public Person(String name, int age) {// 有参构造
- this.name = name;
- this.age = age;
- }
- }
. 之前的对象实例化格式:1Person2per=3new4Person(); 下面针对当前的对象实例化格式与之前的对象实例化格式做一个比较:
. 当前的对象实例化格式:1Person2per=3new4Person("张三",18);
1[1Person] 主要是定义对象的所属类型, 类型决定了你可以调用的方法;
2[2per] 实例化对象的名称;
3[3new] 开辟一块新的堆内存空间;
4[4Person("张三",18)] 调用有参构造,[4Person()] 调用无参构造.
在 Java 的程序里面克绿道程序结构的完整性, 所以所有的类都会提供有构造方法, 也就是说如果现在你的类中没有定义任何构造方法, 那么一定会默认提供一个无参, 什么都不做的构造方法, 这个构造方法是在程序编译的时候自动创建的. 如果你先已经在类中明确的定义有一个构造方法的时候, 那么这个默认的构造方法将不会被自动创建.
结论: 一个类至少存在有一个构造方法, 永恒存在.
疑问:为什么构造方法上不允许设置返回值类型??? 既然构造方法是一个方法,那么为什么不让它定义返回值类型呢? 既然构造方法不会返回数据,为什么不使用 void 定义呢? 分析:程序编译器是根据代码结构来进行编译处理的,执行的时候也是根据代码结构来处理的。 如果在构造方法上使用 void,那么此结构就与普通方法相同了,这样编译器会认为此方法是一个普通方法,普通方法与构造方法最大的区别:构造方法是在类对象实例化的时候调用的,而普通方法是在类对象实例化产生之后调用的。 |
既然构造方法本身是一个方法, 那么方法就具有重载的特点, 而构造方法重载的时候只需要考虑参数的类型及个数即可.
. 范例: 构造方法重载
- class Person {
- private String name;
- private int age;
- public Person(){// 无参构造
- }
- public Person(String name){//1 参构造
- super();
- this.name=name;
- }
- public Person(String name,int age){//2 参构造
- this.name=name;
- this.age=age;
- }
- public void tell(){
- System.out.println("姓名:"+this.name+", 年龄:"+this.age);
- }
- }
经过分析我们知道, setter 与构造方法都可以进行的对象的属性设置, 这个时候一定要清楚构造方法只在对象实例化的时候起作用, setter 本身就是修改数据的功能. 在进行多个构造方法定义的时候强烈建议大家有一些定义的顺序, 例如: 可以按照参数的个数降序或升序排列.
. 定义对象的名称: 类名称 对象名称 = null;
. 实例化对象: 对象名称 = new 类名称 ();
如果这个时候通过实例化对象来进行类的操作也是可以的, 而这种形式的对象由于没有名字就称为匿名对象.
. 范例: 观察匿名对象
- public class Main {
- public static void main(String[] args) {
- new Person("万雨",25).tell();// 匿名对象, 没有引用名称!!!
- }
- }
- class Message{
- private String title;
- public Message(){}
- public Message(String title){
- this.title=title;
- }
- public void setTitle(String title) {// 数据修改
- this.title = title;
- }
- public String getTitle() {// 数据获取
- return this.title;
- }
- }
- class Person{
- private String name;
- private int age;
- public Person(){}
- public Person(String name){
- this.name=name;
- }
- public Person(String name,int age){
- this.name=name;
- this.age=age;
- }
- public Person(Message msg,int age){// 方法重载, 构造方法也是方法
- this.name=msg.getTitle();
- this.age=age;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getName() {
- return this.name;
- }
- public int getAge() {
- return this.age;
- }
- public Message getInfo(){
- return new Message(this.name+":"+this.age);
- }
- public void tell(){
- System.out.println("[姓名]"+this.name+"[年龄]"+this.age);
- }
- }
- public class Main {
- public static void main(String[] args) {
- Message msg=new Message("Mufasa");
- Person person=new Person(msg,25);// 声明对象, 实例化对象
- msg=person.getInfo();
- System.out.println(msg.getTitle());
- }
- }
此时依然通过了对象进行了类中 tell() 方法的调用, 但是由于此对象没有任何的引用名称, 所以该对象使用一次之后就变成了垃圾, 而所有的垃圾都将被 GC 回收与释放.
来源: http://www.bubuko.com/infodetail-3107195.html