JAVA基础编程——面向对象

JAVA基础编程——面向对象,第1张

面向对象并不是JAVA中所独有的,而是一种编程思想,这种编程思想在很多编程语言中都使用到了,如C/C++、Python等,而JAVA自然也引入了面向对象的概念。

面向对象程序设计方法中很重要的三个特性就是:

  • 封装:封装有两层含义:
    • 一是指把对象的属性和行为包装为一个整体
    • 二是将属性和行为与外界进行隔离,可以只暴露给外界有限的信息,而隐藏内部实现细节
  • 继承:继承主要是为了增强代码的复用性,提高软件的开发效率
  • 多态:JAVA和C/C++类似,也存在两种多态形式:
    • 方法重载
    • 对象多态:子类对象可以与父类对象进行相互转换,而根据子类不同其对应可完成功能也不同
语法结构

JAVA中类与对象的定义与C/C++并没有什么不同,只是C/C++称类中的函数为成员函数和成员属性,而JAVA中则称之为属性和方法。

JAVA中类的定义语法为:

class classname {
    datatype prop;
    ...

    public returntype functype(argtype arg,...) {
        // statement;
        [return returntype;]
    }
}

类中的属性在开发中不一定只是变量,也有可能是其它内容,所以也会称之为成员(field)。

如果定义了下边的这样一个类:

class Book {
    String name;
	double price;
	
	public void getInfo() {
	    System.out.println("Book name is " + name + ",book price is " + price);
	}
}

并在main中这样调用:

public class Demo {
	public static void main(String args[]) {
	    Book bk = new Book();
		bk.name = "English";
		bk.price = 12.5;
		bk.getInfo();
	}
}

产生的结果为:

Book name is English,book price is 12.5

从这样看来,JAVA和C/C++的语法结构上还是很相似的。

实例化对象

之前提到,类属于引用数据类型,而引用数据类型会涉及到内存的分配和引用。对象的产生要通过声明并进行实例化:

classname var = new classname();

或者:

classname var = null;
var = new classname();

 上面实例化一个对象用到了new关键字,在C/C++中,new是用来申请内存的。JAVA中同样也可以用来为实例化对象申请内存。而其余类方法的调用与C/C++的使用方法类似。

同样之前在C/C++中也提到,一般变量是放在栈内存当中,一旦声明,统一销毁,而使用new申请的内存则是存放在堆内存当中,随用随开,用完自销。

而JAVA中也有类似的概念:

  • 堆内存:保存每一个对象的属性内容,需要使用new关键字才能够开辟,如果某个对象没有对应的堆内存指向,将无法使用
  • 栈内存:保存的是一块堆内存的地址数据,所以每一块堆内存只能够保留一块堆内存地址

 对于类对象来说,栈内存保存的就是bk这样的引用变量名,而堆内存保存的则是bk实际指向的对象,包含name,price等属性。

而若是只用Book bk = null;声明了对象,但却并没有为其实例化,则会在引用对象属性或调用对象方法的时候出错,因为此时并没有为该应用数据类型开辟堆内存空间。

封装

但是实际情况中,上面的Book并不会这样定义,而是换一种方式:

class Book {
    private String name;
	private double price;
	
	public void getInfo() {
	    System.out.println("Book name is " + name + ",book price is " + price);
	}
	
	public void setName(String var) {
	    name = var;
	}
	
	public String getName() {
	    return name;
	}
	
	public void setPrice(double var) {
	    price = var;
	}
	
	public double getPrice() {
	    return price;
	}
}

在这里,JAVA与C/C++的封装形式开始出现了一些区别,C/C++中使用public:/private:来分割不同访问类型的属性或者方法,而JAVA这里则是将访问类型放在了属性或方法定义的最前方。

也因此,使用private对属性进行封装,而使用public对外界开放方法接口,才形成了隔离和实现隐藏,这也就是封装的含义。同时,为了能够自定义属性内容,可以自定义的属性最好要设定setter和getter方法。

而此时,该类的使用和方法调用就变为了:

public class Demo {
	public static void main(String args[]) {
	    Book bk = new Book();
		bk.setName("English");
		bk.setPrice(12.5);
		bk.getInfo();
	}
}
构造

上边的形式虽然可以自定义属性内容,但是C/C++中利用构造函数可以在实例化对象的同时就对属性进行赋值,JAVA当然也存在这样的功能:

class Book {
    private String name;
	private double price;
	
	public Book() {
	    System.out.println("This is Book's constructer.");
	}
	
	public Book(String name, double price) {
        this.name = name;
		this.price = price;
	}
	
	public void getInfo() {
	    System.out.println("Book name is " + name + ",book price is " + price);
	}
	
	public void setName(String var) {
	    name = var;
	}
	
	public String getName() {
	    return name;
	}
	
	public void setPrice(double var) {
	    price = var;
	}
	
	public double getPrice() {
	    return price;
	}
}

C/C++中的构造函数是当实例化对象时发生调用,方法名称与类名相同,没有返回值,可以进行重载。而JAVA中的构造方法基本也是一样的用法,在上面的代码段中添加了两个构造方法。对应的,此时的main方法就可以修改为:

public class Demo {
	public static void main(String args[]) {
	    Book bk = new Book();
		bk.getInfo();
		
		Book bk2 = new Book("English",12.5);
		bk2.getInfo();
	}
}

执行结果为:

This is Book's constructer.
Book name is null,book price is 0.0
Book name is English,book price is 12.5

从上面的例子可以看出,和C/C++一样,JAVA中也存在一个默认无参的构造方法。这也就是实例化类对象要用Book()而不是Book的缘故。

构造方法一般是用于对象的初始化,而若是存在自定义的构造方法,便会覆盖原有的默认无参构造方法,因此为了Book()实例化对象不至于报错,同时应该存在自定的无参构造方法。

而属性也可以存在默认值,这点在log打印或者表达文件路径中经常用到,这里先说明一下用法:

class Book {
	private int VERSION = 1;
    private String name;
	private double price;
	
	public Book() {
	    System.out.println("This is Book's constructer, version is " + VERSION);
	}
	
	public Book(String name, double price) {
        this.name = name;
		this.price = price;
	}
	
	public void getInfo() {
	    System.out.println("Book name is " + name + ",book price is " + price + ",version is " + VERSION);
	}
	
	public void setName(String var) {
	    name = var;
	}
	
	public String getName() {
	    return name;
	}
	
	public void setPrice(double var) {
	    price = var;
	}
	
	public double getPrice() {
	    return price;
	}
}

如上面的代码所示,添加了一个默认属性VERSION,因为直接给了默认值,这里将该属性写为了大写,同时没有给出setter方法。此时进行实例化:

public class Demo {
	public static void main(String args[]) {
	    Book bk = new Book();
		bk.getInfo();
	}
}

结果为:

This is Book's constructer, version is 1
Book name is null,book price is 0.0,version is 1

对象实例化的过程,一般要经历类的加载,内存的分配,默认值的设置,构造方法。而构造方法属于整个对象构造过程的最后一步,这一步是留给用户自己处理的步骤。

而在上面的结果显示中,VERSION这个变量却在自定义的构造方法调用之前就完成了赋值,所以对于用户来说,其VERSION属性就是默认值。

匿名对象

匿名对象从名称来说就是没有名字的对象。之前提到栈内存中保存着对象的变量名,而其实际的属性和方法则保存在堆内存中,由栈内存的变量名指向该堆内存,完成引用和访问。

而匿名对象很显然就是省略了变量名,换句话说也就是没有在栈内存中进行声明,而却仍能够指向某块堆内存。考虑下面的代码段:

public class Demo {
	public static void main(String args[]) {
	    new Book().getInfo();
	}
}

结果为:

This is Book's constructer, version is 1
Book name is null,book price is 0.0,version is 1

在上面的代码中,并没有变量指向Book对象,但是仍然开辟了堆内存,完成了方法调用。而由于这种方法创建的匿名对象并没有对应的栈内存指向,所以只能使用一次,之后由于没有栈内存明确地指向该堆内存,就会被GC(Garbage Collector)回收释放。

this

同时上面的代码中还用到了另一个关键字this,和C/C++一样,this指向了当前的对象,以表示和传入参数进行区分。

上面this只是调用的本类中的属性,除此之外还可以调用本类方法:

  • 调用本类普通方法:可以使用 this.func() 调用
  • 调用本类构造方法:在一个构造中要调用其它构造,可以使用 this() 调用

将上边的代码修改为:

class Book {
    private String name;
	private double price;
	
	public Book() {
	    System.out.println("This is Book's constructer.");
	}
	
	public Book(String name, double price) {
		this();
        this.name = name;
		this.price = price;
	}
	
	public void getInfo() {
	    System.out.println("Book name is " + name + ",book price is " + price);
	}
	
	public void setName(String var) {
	    name = var;
	}
	
	public String getName() {
	    return name;
	}
	
	public void setPrice(double var) {
	    price = var;
	}
	
	public double getPrice() {
	    return price;
	}
}

然后:

public class Demo {
	public static void main(String args[]) {
	    Book bk = new Book("English",12.5);
		bk.getInfo();
	}
}

此时的结果为:

This is Book's constructer.
Book name is English,book price is 12.5

也就实现了this对构造方法的调用。但同时使用this调用构造方法时,也会存在两个限制:

  • 使用 this() 调用构造方法形式的代码只能够放在构造方法的首行
  • 进行构造方法互相调用时,要保留调用的出口
简单JAVA类

透过上面的过程,也差不多能够搞清楚JAVA类的使用和定义方法了。这里再说明下简单JAVA类的基本开发要求:

  • 类名称必须存在意义
  • 类中所有的属性必须用private进行封装
  • 类中可以提供任意多个构造方法,但必须保留一个无参构造方法
  • 类中不允许出现任何输出语句,所有信息输出必须交给被调用处输出
  • 类中需要提供有一个取得对象完整信息的方法,而且返回String型数据

上面的要求结合之前的说明和理解便可以明白,这里不赘述。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/795422.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存