阿里云名师课堂Java面向对象开发3 ~ 6:类与对象

Posted 溺水的情书

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里云名师课堂Java面向对象开发3 ~ 6:类与对象相关的知识,希望对你有一定的参考价值。

类与对象的基本定义

是面向对象设计的核心所在,也是所有概念的基础。类本身属于引用数据类型,因此类的使用牵扯到内存的分配问题。

认识类与对象

类指的是一个共性的概念,而对象指的是一个具体的事物。
因此,在实际的开发过程中吧,一定是要首先产生类,而后才可以产生我们的对象。那么对象的所有行为都一定在类中进行了完整的定义。类中没有定义的功能,对象一定无法实现。
类的组成:

  • 方法(操作的行为、定义的功能)
  • 属性(变量,描述每一个对象的具体特点)

类与对象定义及使用

使用class关键字进行类的定义。

		class 类名称 {
			属性 ;
			属性 ;
			······
			方法(){}  // 此时的方法不在由主类直接调用,而是要通过对象进行调用
		}
  • 范例:观察定义类操作
class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age)
	}
}

在这个类中只是定义了两个属性一个方法,而类中可以定义的属性数量与方法数量都没有限制。在编写时每个方法中的代码尽量不要特别长。
类产生之后是不能直接使用的,如果要使用的话必须要定义对象(实例化)。而对象的定义分为以下两种语法形式:

  • 声明并实例化对象:类名称 对象名称 = new 类名称() ;
  • 分步进行对象实例化
    • 声明对象:类名称 对象名称 = null ;(所有变量在定义时都要有值,类的默认值是空null
    • 实例化对象:对象名称 = new 类名称() ;

引用数据类型的最大特征在于内存的分配操作,而只要出现了关键字new,就有开辟新内存。而内存是不能无限开辟的,所以所谓的性能调优就是调整的内存问题。

  • 范例:声明并实例化对象
class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age)
	}
}

public class TestDemo {    // 定义一个程序类
	public static void main(String args[]) {
		// 类名称 对象名称  = new 类名称() ;
        Person per = new Person() ; // 这时就实例化了一个per对象
    } 
} 

所有的对象只有实例化之后才可以真正使用,而对象的使用都是围绕着类进行的,那么此时有两种形式:

  • 调用类中的属性:对象.属性 = 内容 ;
  • 调用类中的方法:对象.方法() ;
    实例:观察一个最基本的类的定义以及对象的使用操作形式。
class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age) ;
	}
}

public class TestDemo {    // 定义一个程序类
	public static void main(String args[]) {
		// 类名称 对象名称  = new 类名称() ;
        Person per = new Person() ; // 这时就实例化了一个per对象
		per.name = "Dexter" ;  // 设置per对象中的name属性
		per.age = 20 ;  // 设置per对象中的age属性
        per.info() ;
		// 输出:name = Dexter age = 20
    } 
} 

对象内存分析

想要知道对象的产生分析,首先必须清楚引用类型。引用类型指的是内存空间的操作。重点在两块内存空间:

  • 内存空间:保存真正的数据,对象的属性信息;
  • 内存空间:保存堆内存的地址,简单理解:保存的是对象名称

声明并实例化对象的内存分析

技术图片
上一个实例程序的内存对象分析图解。new在堆内存中开辟了新的堆内存来保存属性(最初是初始值),这个堆内存的地址(图中OX0001)被保存在栈内存中,可以理解为栈内存中保存的就是对象名,因为通过对象名.类名可以修改堆内存中属性的值。
声明并实例化一个对象的格式在这里分析结束,下面分析分步进行对象实例化。

分步进行对象实例化的内存分析

  • 实例:分步进行对象实例化
class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age) ;
	}
}

public class TestDemo {    // 定义一个程序类
	public static void main(String args[]) {
		// 类名称 对象名称  = new 类名称() ;
        Person per = null ;  // 声明一个新的对象per
		per = new Person() ; // 实例化per对象
		per.name = "Dexter" ;  // 设置per对象中的name属性
		per.age = 20 ;  // 设置per对象中的age属性
        per.info() ;
		// 输出:name = Dexter age = 20
    } 
} 

观察内存分析图:
技术图片
注意:对象(乃至所有的引用数据类型:数组、类、接口)必须在其开辟空间后才可以使用。如果使用了未开辟空间的引用数据类型,虽然编译时不会报错,但是会在执行时出现NullPointerException:

  • 范例;观察一个错误代码:
class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age) ;
	}
}

public class TestDemo {    // 定义一个程序类
	public static void main(String args[]) {
		// 类名称 对象名称  = new 类名称() ;
        Person per = null ;  // 声明一个新的对象per
        per.info() ;
    } 
} 

技术图片
错误出现在第13行,是per对象调用Person类中的info方法。因为只声明对象而没有实例化对象,只在栈空间开辟内存而没有在堆空间开辟内存,所以无法使用这个对象,当然也不能调用类中的方法。

引用传递初次分析(重点)

引用传递通俗理解:一个人的大名、小名、外号等,这些别名放在栈内存之中,人在堆内存之中。即:一块堆内存可以被多个栈内存所指向。如果这个人的某样东西(类的属性、方法)丢失了,那么所有别名指向的这样东西都丢失(都无法调用)。
范例:观察引用传递

class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age) ;
	}
}

public class TestDemo {    // 定义一个程序类
	public static void main(String args[]) {
		// 类名称 对象名称  = new 类名称() ;
        Person per1 = new Person() ;
        per1.name = "Dexter" ;
		per1.age = 20 ;
		per1.info() ;
		// 此步骤就是引用传递的操作
		Person per2 = per1 ;  // 采用同样的类型接收
		per2.name = "tsukishima kei" ;
		per1.info() ;
		per2.info() ;
    }
} 

对象per1和per2都是类Person的外号,都指向Person。通过二者任意一个调用Person中属性,Person属性都会得到修改。
技术图片
观察内存分析图
技术图片
范例:还是观察引用传递

class Person {  // 定义一个类,注意类名称每个单词首字母大写
	String name ;  // 属性1,表示人的姓名
	int age ;  // 属性2,表示人的年龄
	public void info() {  // 一个方法
		System.out.println("name = " + name + " age = " + age) ;
	}
}

public class TestDemo {    // 定义一个程序类
	public static void main(String args[]) {
		// 类名称 对象名称  = new 类名称() ;
        Person per1 = new Person() ;
        per1.name = "Dexter" ;
		per1.age = 20 ;
		per1.info() ;
		Person per2 = new Person() ;  // 有new就会开辟新的内存空间
		per2.name = "toono takaki" ;
		per2.age = 14 ;
		per2.info() ;
		per2 = per1 ;  // 已在main定义了变量 per2,不需要再加上Person
		per2.name = "tsukishima kei" ;
		per1.info() ;
		per2.info() ;
    }
} 

技术图片
观察内存分析图:
技术图片
垃圾内存空间:没有任何栈内存指向的堆内存空间,所有的垃圾空间将不定期被Java中的Garbage Collector回收以实现内存空间的释放。不过从实际开发来讲,虽然Java提供有GC,但是GC也会造成程序性能的下降。所以开发过程中一定要控制好对象的产生数量,即:无用的对象尽可能少产生。


















以上是关于阿里云名师课堂Java面向对象开发3 ~ 6:类与对象的主要内容,如果未能解决你的问题,请参考以下文章

阿里云名师课堂Java面向对象开发40:引用传递实际应用

阿里云名师课堂Java面向对象开发68 ~ 7073:接口的定义和使用

名师课堂Java面向对象开发

阿里云名师课堂Java面向对象开发97 ~ 105:链表

阿里云名师课堂Java面向对象开发71 ~ 72:接口的设计模式

阿里云名师课堂Java面向对象开发41:第03个代码模型综合案例:数据表与简单Java类(一对多)