导图社区 Java类和对象
对象就是客观世界中存在的人、事和物体等实体。在现实世界中,对象随处可见,例如,路边生长的树、天上飞的鸟、水里游的鱼和路上跑的车等。不过这里说的树、鸟、鱼和车都是对同一类事物的总称,这就是面向对象中的类(class)。这时读者可能要问,那么对象和类之间的关系是什么呢?对象就是符合某种类定义所产生出来的实例(instance),虽然在日常生活中我们习惯用类名称呼这些对象,但是实际上看到的还是对象的实例,而不是一个类。例如,你看见树上落着一只鸟,这里的“鸟”虽然是一个类名,但实际上你看见的是鸟类的一个实例对象,而不是鸟类。由此可见,类只是个抽象的称呼,而对象则是与现实生活中的事物相对应的实体。
编辑于2022-11-22 14:44:14 贵州微信小程序开发知识整理,系统地介绍了微信小程序开发的基础知识,帮助开发者更好地理解和掌握小程序开发的要点和流程。
SpringFramework技术的介绍,SpringFramework,通常简称为Spring,是一个开源的企业级Java应用程序框架,由Rod Johnson创建,并于2004年首次发布。Spring Framework的主要目标是简化企业级Java开发,提高开发效率和应用程序的可维护性。
Maven的特性以及使用部署方法,Maven介绍:Maven是一款为Java项目构建管理、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
社区模板帮助中心,点此进入>>
微信小程序开发知识整理,系统地介绍了微信小程序开发的基础知识,帮助开发者更好地理解和掌握小程序开发的要点和流程。
SpringFramework技术的介绍,SpringFramework,通常简称为Spring,是一个开源的企业级Java应用程序框架,由Rod Johnson创建,并于2004年首次发布。Spring Framework的主要目标是简化企业级Java开发,提高开发效率和应用程序的可维护性。
Maven的特性以及使用部署方法,Maven介绍:Maven是一款为Java项目构建管理、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
Java面向对象概述
一、 面向对象概述
(1) 面向对象概述
类只是个抽象的称呼,而对象则是与现实生活中的事物相对应的实体。类与对象的关系如图1所示。
类实质上是对象的蓝图,类里面包含了对象的属性和方法
在现实生活中,只是使用类或对象并不能很好的描述一个事物,例如,婷婷对妈妈说我今天放学看见一只鸟,这时妈妈就不会知道婷婷说的鸟是什么样子的。但是如果婷婷说看见一只绿色的会说话的鸟,这时妈妈就可以想象到这只鸟是什么样的。这里说的绿色是指对象的属性,而会说话则是指对象的方法。由此可见,对象还具有属性和方法。在面向对象程序设计中,使用属性来描述对象的状态,使用方法来处理对象的行为。
(2) 对象
在计算机的世界中,面向对象程序设计的思想要以对象来思考问题,首先要将现实世界的实体抽象为对象,然后考虑这个对象具备的属性和行为。例如现在面临一只大雁要从北方飞往南方这样一个实际问题,试着以面向对象的思想来解决这一实际问题,步骤如下:
1||| 首先可以从这一问题中抽象出对象,这里抽象出的对象为大雁
2||| 然后识别这个对象的属性,对象具备的属性都是静态属性,例如大雁具有一对翅膀,一双脚等,这些属性如图2所示
图2
3||| 接着是识别这个对象的动态行为,即这只大雁可以进行的动作,例如飞行、觅食等,这些行为都是因为这个对象基于这些对象属性而具有的动作,这些行为如图3所示。
图3
4||| 识别出这些对象的属性和行为后,这个对象就被定义完成,然后可以根据这只大雁具有的特性制定这只大雁要从北方飞向南方的具体方案以解决问题。实质上究其本质,所有的大雁都具有以上的属性和行为,可以将这些属性和行为封装起来以描述大雁这类动物。由此可见,类实质上就是封装对象属性和行为的载体,而对象则是类抽象出来的一个实例,二者之间的关系如图4所示。
图4
(3) 类
类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。例如一个鸟类,鸟类封装了所有鸟的共同属性和应具有的行为,它的结构如图所示
定义完成鸟类之后,可以根据这个类抽象出一个实体对象,最后通过实体对象来解决相关一些实际问题
图5
(4) 封装
面向对象程序设计具有以下特点:
1||| 封装性
2||| 继承性
3||| 多态性
封装是面向对象编程的核心思想,将对象的属性和行为封装起来,而将对象的属性和行为封装起来的载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。例如用户使用电脑,只需要使用手指敲击键盘就可以实现一些功能,用户无须知道电脑内部是如何工作的,如果用户可能碰巧知道电脑的工作原理,但在使用电脑时并不完全依赖于电脑工作原理这些细节。采用封装的思想保证了类内部数据结构的完整性,应用该类的用户不能轻易直接的操纵此数据结构,用户只能执行类允许公开的数据。这样避免了外部对内部数据的影响,提高程序的可维护性
(5) 继承
当处理一个问题时,可以将一些有用的类保留下来,当遇到同样问题时拿来复用,假如这时需要解决信鸽送信的问题,由于鸽子属于鸟类,鸽子具有鸟类相同的属性和行为,但并不是所有的鸟都有送信的习惯,但可以在创建信鸽类时将鸟类拿来复用,并且保留鸟类具有的属性和行为,然后再添加一些信鸽独特具有的属性以及行为,鸽子类保留了鸟类的属性和行为,这样就节省了定义鸟和鸽子共同具有的属性和行为的时间,这就是继承的基本思想。可见软件的代码使用继承思想可以缩短软件开发的时间,复用那些已经定义好的类可以提高系统性能,减少系统在使用过程中出现错误的几率
(6) 多态
父类对象应用于子类的特征就是多态,依然以图形类来说明多态,每个图形都拥有绘制自己的能力,这个能力可以看作是该类具有的行为,如果将子类的对象统一看作是超类的实例对象,这样当绘制任何图形时,可以简单地调用父类也就是图形类绘制图形的方法即可绘制任何图形。这就是多态最基本的思想。
二、 类
(1) 类的定义
类是用来定义一组对象共同具有的状态和行为的模板。而对象是现实世界中个体或事物的抽象表示,并封装了它们的属性和行为,例如一个员工可以表示为一个对象,它有姓名、性别、年龄等属性,同时也具有吃、喝、走、跑、说话等行为。这些属性和行为都是“人类”所具有的,也就是说类声明了这些共同的特性,对象(也就是类的实例)在使用之前,必须定义该对象的类,知道了对象的类型,才能够访问它的属性和行为
语法格式: class className{ 成员变量 ... ... 成员方法 ... ... }
其中className是要定义的类的名称,在类体中可以定义多个成员变量和成员方法,在之前的实例中,经常使用的是main()方法,这就是一种特殊的成员方法,因为它作为程序执行的入口方法,用于执行程序。
实例代码: public class Fruit { public String color=""; //定义颜色成员变量 public void plan(){ System.out.println("果树正在种植"); //定义种植成员方法 } public void grow(){ System.out.println("果树正在成长"); //定义生长的成员方法 } public void harvest(){ System.out.println("水果已经收获"); //定义收获的成员方法 } public static void main(String[] args) { Fruit apple=new Fruit(); //对象实例化 System.out.println("这是一颗苹果树"); apple.plan(); //调用方法 apple.grow(); apple.harvest(); } }
运行结果: 这是一颗苹果树 果树正在种植 果树正在成长 水果已经收获
(2) 成员变量
成员变量是在类体中定义的变量,即全局变量,成员变量用于定义对象的状态。例如Student类有name、age、sex等成员变量分别表示姓名、年龄、性别等状态。如右图所示
成员变量必须直接定义在类体中,如果定义在其他方法或代码块中,就会成为局部变量,而不是成员变量。
(3) 成员方法
成员方法是对象行为的描述。每个方法都是由复合语句描述相应的行为。定义成员方法的语法格式如下:
1||| 修饰符:可以是public、private、protected以及static、final等。修饰符是可选的语法部分
2||| 返回值类型:如果方法需要返回值,必须在这里声明方法的返回值类型,可以使基本数据类型(int、short、double、boolean等),也可以是对象类型(例如数组、字符串等)
3||| 方法名:这是必须的方法定义部分,程序将通过该名称调用这个方法
4||| 形参表:这是可选部分,说明方法被调用时,应该向它传递的数据
形参表由1到多个形式参数构成,当方法有多个形式参数时,参数之间使用“,”逗号分割;如果方法没有参数,可以省略“形参表”部分
例如:public void saveBookInfo(String bookName, String publishing, String writer) { //方法体 }
这段代码定义了saveBookInfo()方法实现图书信息的保存,最简单的图书信息也要有书名、出版社、作者等信息,所以该方法的形参表定义了bookName、publishing和writer参数。
(4) 权限修饰符
Java中的权限修饰符主要包括private、public和protected,这些修饰符控制着对类和类的成员变量以及成员方法的访问。如果一个类的成员变量或成员方法被修饰为private,这成员变量只能在本类中被使用,在子类中是不可见的,并且对其他包的类也是不可见的。如果将类的成员变量和成员方法的访问权限设置为public,除了可以在本类使用这些数据之外,还可以在子类和其他包中的类中使用。如果一个类的访问权限被设置为private,这个类将隐藏所其内的所有数据,以免用户直接访问它。如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为public访问权限。如果一个类使用protected修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和成员方法。 这么看来,public和protected修饰的类可以由子类访问,如果子类和父类不在同一包中,那么只有修饰符为public的类可以被子类进行访问。如果父类不允许通过继承产生的子类访问它的成员变量,那么必须使用private声明父类的这个成员变量。右图中描述了private、protected、public修饰符的修饰权限。
(5) 局部变量
如果在成员方法内定义一个变量,那么这个变量被称为局部变量,局部变量只在定义它的方法内有效
(6) 局部变量的有效范围
可以将局部变量的有效范围称为变量的作用域,局部变量的有效范围从该变量的声明开始到该变量的结束为止。右图描述局部变量的作用范围
在相互不嵌套的作用域中可以同时声明两个名称、类型相同的局部变量
但是在相互嵌套的区域中不可以这样声明,如果将局部变量id值在方法体的for循环中再次定义,编译器将会报错
(7) this关键字
private void setName(String name){ //定义一个setName()方法 this.name=name; //将参数值赋予类中的成员变量 }
成员变量与在setName()方法中的形式参数的名称相同,都为name,那么如何在类中区分使用的是哪一个变量?在Java语言中规定使用this关键字来指定,this关键字被隐式的用于引用对象的成员变量和方法,如在上述代码中,this.name指定的就是Book类中的name成员变量,而this.name=name语句中的第二个name则指定的是形参name。实质上setName()方法实现的功能就是将形参name的值赋予给成员变量name。
三、 类的构造方法
在类中除了成员方法之外,还存在一种特殊类型的方法,那就是构造方法,构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的,其功能主要是完成对象的初始化,每当类实例化一个对象时,类都会自动调用构造方法。 构造方法的特点如下:
1||| 声明构造方法没有返回值类型
2||| 构造方法的名称要与本类的名称相同
在定义构造方法时,构造方法没有返回值,但这与普通没有返回值的方法不同,普通没有返回值的方法使用public void methodEx()这种形式进行定义,但构造方法并不需要void关键字进行修饰。构造方法的定义语法形式如下: public 类名([参数列表]){ //...构造方法体 }
I. public:构造方法修饰符
II. 类名:构造方法的名称,它必须和类名相同
III. 参数列表:可选参数,可以定义多个参数为构造方法传参,也可以不定义参数,使用没有任何参数的默认构造方法
如果类中没有明确定义任何构造方法,则编译器会自动创建一个不带参数的默认构造方法。 在构造方法中可以完成变量赋值、连接数据库等初始化工作,这样当实例化一个本类的对象时,相应初始化工作就自动完成了。 和成员方法一样,构造方法也可以重载,定义参数列表不同的多个构造方法可以创建并初始化不同的对象。例如Student类的构造方法可以根据传递的姓名、性别、年龄等不同参数的值,来创建不同的学生对象,这些参数在程序中可能来源于现实世界,类似招生人员登记学生信息时,招生人员就是构造方法,每个学生都是一个对象,而它们的信息就是构造方法的参数。如右图所示。你甚至可以为Student类添加指纹、血型等属性来进一步区别每个学生对象,但是那基本上超出了程序的业务范围。所以,在定义类的时候,要选择合适的属性和行为进行定义
实例代码: public class Student { public String name; public String sex; public int age; public Student(){ name="未登记"; sex="未登记"; age=0; /* 不带参数的构造方法 */ } public Student(String name){ this.name=name; // this关键字防止参数name覆盖成员变量 /* 初始化姓名的构造方法 */ } public Student(String name,String sex,int age){ this(name); this.sex=sex; this.age=age; /* 初始化学生信息的方法 */ } public void displayInformation(){ System.out.println("姓名:"+name); System.out.println("性别:"+sex); System.out.println("年龄:"+age); } public static void main(String[] args) { Student s1=new Student(); Student s2=new Student("张三"); Student s3=new Student("李四","男",24); s1.displayInformation(); s2.displayInformation(); s3.displayInformation(); } }
运行结果: 姓名:未登记 性别:未登记 年龄:0 姓名:张三 性别:null 年龄:0 姓名:李四 性别:男 年龄:24
四、 静态变量、常量和方法
有时在处理问题时,会需要两个类在同一个内存区域共享一个数据,比如在球类中使用PI这个常量,可能除了本类需要这个常量之外,在另外一个圆类中也需要使用这个常量,这时没有必要在两个类中同时创建PI这个常量,因为系统会将这两个不在同一个类中定义的常量分配到不同的内存空间中,为了解决这个问题可使用static关键字将这个常量设置为静态的。
被声明为static的变量、常量和方法被称为静态成员。静态成员是属于类所有的,区别于个别对象,可以在本类或其他类使用类名和“.”运算符调用静态成员
实例代码: public class jt { static float Pi= 3.14f; //定义静态成员变量PI static float r=2.5f; public float area(){ return Pi*r*r; /* 计算圆面积 */ } public float round(){ return 2*Pi*r; /* 计算圆周长 */ } public static void main(String[] args) { jt j=new jt(); System.out.println("圆面积:"+j.area()); System.out.println("圆周长:"+j.round()); } }
运行结果: 圆面积:19.625 圆周长:15.700001
五、 类的主方法
主方法是类的入口点,它定义了程序从何处开始,主方法提供对程序流向的控制,Java编译器通过主方法来执行程序。语法如下: public static void main(String[] args){ //方法体 }
从主方法的定义中可以看到主方法具有如下几点特性:
1||| 主方法也是静态的,所以要直接在主方法中调用其他方法,则该方法必须也是静态的
如果在主方法中调用非静态方法时,可以先实例化该类,再通过类的实例调用相应的方法
2||| 主方法没有返回值
3||| 主方法的形参为数组。其中args[0]~args[n]分别代表程序的第一个到第n个参数,可以使用args.length获取参数的个数
六、 对象
1. 对象的创建
每个对象都是相互独立的,在内存中占据独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象变成了垃圾,由Java虚拟机自带的垃圾回收机制处理。不能再被使用
创建类的实例对象需要使用new语句,声明并创建对象的语法格式如下: 类名 对象名=new 类构造方法();
类名:这是要创建实例对象的类的名称
对象名:它可以看作是一个变量,这个变量名就是创建的实例对象的名称
构造方法:是类创建对象时必须执行的方法,用于构造一个新的对象并初始化对象属性
例如:String name = new String("一个新的字符串对象");
这句代码声明了字符串变量name,并且使用new语句创建了字符串对象,String是一个特殊的类,它可以使用双引号的字面量创建对象,也可以使用new语句创建,但是我们自己写的类,只能使用new语句创建注
2. 访问对象的属性和行为
在Java中,创建对象以后,可以访问对象的属性,即成员变量。访问对象属性需要使用“.”操作符
3. 对象的引用
在Java语言中尽管一切都可以看作对象,但真正操作标识符实质上是一个引用
例如:Book book= new Book();
通常一个引用不一定需要有一个对象相关联,比如Book book;
引用只是存放一个对象的内存的地址,并非存放一个对象,严格说引用和对象是不同的,但是可以将这种区别忽略,如可以简单的说book是Book类的一个对象,而事实上应该是book是包含Book对象的一个引用
4. 对象的比较
在Java语言中有两种对象的比较方式,分别为“==”运算符与equals()方法,实质上这两种方式有本质区别
实例代码: public class equalTest { public static void main(String[] args) { String s1=new String("zbc"); //创建String型对象引用 String s2=new String("zbc"); System.out.println("s1==s2的结果为:"+(s1==s2)); System.out.println("s1.equals(s2)的结果为"+(s1.equals(s2))); } }
运行结果: s1==s2的结果为:false s1.equals(s2)的结果为true
从运行结果中可以看出,“==”运算符和equals()方法比较的内容是不相同的,equals()方法是String类中的方法,它用于比较两个对象引用所指的内容是否相等。而“==”运算符比较的是两个对象引用的地址是否相等
5. 对象的销毁
Java语言提供了垃圾回收机制,对于不再使用的对象会自动销毁,也可以在程序中显示的为某个对象赋值null值,使对象不再被使用。虽然垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new操作符创建的对象,如果某些对象不是通过new操作符在内存中获取一块内存区域,这种对象可能不被垃圾回收机制所识别,所以在Java中提供了一个finalize()方法,这个方法是Object类的方法,它被声明为protected,用户可以在自己的类中定义这个方法,如果用户在类中定义了finalize()方法,在垃圾回收时首先调用该方法,并且在下一次垃圾回收动作发生时,才能真正回收对象占用的内存
有一点需要明确的是,垃圾回收或是finalize()方法不保证一定会发生,比如Java虚拟机面临内存损耗待尽的情形,它是不会执行垃圾回收的。 由于垃圾回收不受人为控制,具体执行时间也不确定,所以finalize()方法也就无法执行,为此,Java提供了System.gc()方法强制启动垃圾回收器,这与给120打电话通知医院来救护的道理一样,告知垃圾回收器来清理