分析类与对象

1、学习内容

1、封装的目的;
2、封装的实现;
3、构造方法的定义语法以及调用时机;
4、匿名对象的基本使用;

2、具体内容

2.1、封装的目的和实现
我们先观察一段代码:

  class Book{
    String title;
    int price;
	public void getInfo(){
		System.out.println("图书名称:"+title+"图书价格"+price);
	}
}
public class TestDemo{
	public static void main(String args[]){
		Book book=new Book();
		book.title="java开发";
		book.price=-23;
		book.getInfo();
	}
}
  • 以上的代码之中的没有任何的语法错误,但是却存在业务逻辑上的错误,书的价格为负数,造成此问题的核心是:对象可以在一个类的外部直接访问属性,需要将Book类中的属性设置为对外不可见。

修改之后的程序:

class Book{
    private String title;
    private int price;
    public Book(String title,int price){
    	this.title=title;
    	this.price=price;
    }
	public void getInfo(){
		System.out.println("图书名称:"+title+"图书价格"+price);
	}
}
public class TestDemo{
	public static void main(String args[]){
		Book book=new Book("java",23);
		book.getInfo();
	}
}

针对属性的定义:所有类中的定义的属性都要求使用private声明,如果属性需要被外部所使用,按照要求定义相应的setter,getter方法,以String title为例。

  • setter方法主要是设置内容,public void setTitle(Stirng t),有参;

  • getter方法主要是取得属性的内容:public String getTitle().无参。
    范例:为Book类中的封装属性设置setter、getter方法

     class Book{
          private String title;
          private int price;
       
      	public String getTitle() {
      		return title;
      	}
      	public void setTitle(String title) {
      		this.title = title;
      	}
      	public int getPrice() {
      		return price;
      	}
      	public void setPrice(int price) {
      		if(price>0){
      			this.price=price;
      		}else{
      		}
      	}
      	public void getInfo(){
      		System.out.println("图书名称:"+title+"图书价格"+price);
      	}
      }
      public class TestDemo{
      	public static void main(String args[]){
      		Book book=new Book();
      		book.setPrice(-23);
      		book.setTitle("java程序");
      		book.getInfo();
      	}
      }
    

在开发中验证是由其他辅助的代码完成的,而在实际的开发中,setter往往是简单的设置数据,getter往往是简单的取得数据而已。

2.2、构造方法的使用

分析类与对象

  class Book{
    	public Book(){
    		System.out.println("*********");
    	}
    }
    public class TestDemo{
    	public static void main(String[] arg){
    		Book book=null;//声明对象,没有开辟堆内存空间
    		book=new Book();//实例化对象,开辟堆内存空间
    	}
    } 

通过以上代码可以发现,所有构造方法都在对象使用关键字new实例化的时候默认调用。
构造方法与普通方法的最大区别:

  • 构造方法是在实例化对象(new)的时候只被调用一次
  • 普通方法是在实例化对象产生后可以随意调用多次

既然构造方法是在对象实例化的时候使用的,这样的做法有什么用处?

class Book{
    private String title;
    private int price;
    public Book(String title,int price){
    	this.title=title;
    	setPrice(price);
    } 
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		if(price>0){
			this.price=price;
		}else{
		}
	}
	public void getInfo(){
		System.out.println("图书名称:"+title+"图书价格"+price);
	}
}
public class TestDemo{
	public static void main(String args[]){
//		在实例化对象的同时将所需要的属性传递到对象的构造方法里
		Book book=new Book("java程序",34);//使用默认的构造方法
		book.getInfo();
	}
}

构造方法的核心作用是:在类对象实例化的时候设置对象的初始化内容,或者说构造方法是为属性初始化准备的。
如果一个类中已经明确的定义了一个构造方法,那么不会自动生成默认的构造方法,一个类中至少保留一个构造方法,构造方法可以重载,构造方法重载时,参数个数或类型不同即可。
范例:构造方法重载

class Book{
    private String title;
    private int price;
    public Book(String title){
    	this.title=title;
    	System.out.println("有一个参数的构造方法");
    }
    public Book(String title,int price){
    	this(title);
    	this.price=price;
    	System.out.println("有两个参数的构造方法");
    }

	public void getInfo(){
		System.out.println("图书名称:"+title+"图书价格"+price);
	}
}
public class TestDemo{
	public static void main(String args[]){
		Book book=new Book("java程序",34);
		book.getInfo();
	}
}

在进行构造方法的重载时:请按照参数的个数升序编写,这样好看(呵呵)。

  • 问题:在定义一个类的时候可以为属性直接设置默认值,但是这个默认值只有在构造执行完后才会设置,而构造方法是属于整个对象构造过程的最后一步,即:是留给用户处理的步骤。

在对象实例化的过程中,一定会经历类的加载、内存的分配、默认值的设置、构造方法。
2.4、匿名对象
在上述程序中,只有整个构造方法都完成之后,才会真正将“java开发”这个字符串的内容设置给title属性,在没有构造之前title都是其对应属性的默认值。
那么有了构造方法的概念,实际上就可以依照此方式使用匿名对象,之前定义都是有名对象,所有的对象都给了一个名字,但是这个名字真正使用的时候调用的是堆内存空间,即:真实的对象信息保存在堆内存之中,那么没有栈指向的对象就称为匿名对象。

class Book{
	private String title;
	private int price;
	public Book(String title,int price){
		this.title=title;
		this.price=price;
	}
	public void getInfo(){
		System.out.println("书名:"+title+","+"价格"+price);
	}
}
public class TestDemo{
	public static void main(String args[]){
		new Book("java",33).getInfo();
	}
}
  • 但是匿名对象由于没有其它对象进行引用,所以只能只用一次,一次之后该对象空间将成为垃圾,等待回收。

3、总结

  1. 封装性就是保证内部的定义被外部不可见;
  2. 所有属性都必须使用private封装,封装后的属性如果要被外部所访问,要定义setter,getter方法;
  3. 构造方法的定义要求:方法名称与类名称相同,无返回值声明;
  4. 构造方法是在类对象使用关键字new实例化对象的时候被默认调用的,一个类中至少保留一个构造方法,无自己定义的构造方法,则程序会有默认的构造方法;
  5. 构造方法重载时,考虑参数的个数和类型即可,且构造方法只使用一次;
  6. 对象信息保存在堆内存之中,那么没有栈指向的对象就称为匿名对象。