网站建设课程设计报告图文,设计网站首页多少钱,视频营销,专业做官网的公司类和对象#xff08;中#xff09;4. this引用4.1 为什么要有this引用4.2 什么是this引用4.3 this引用的特性5. 对象的构造及初始化5.1 如何初始化对象5.2 构造方法#xff08;构造器#xff09;5.2.1 概念5.2.2 特性5.3 默认初始化5.4 就地初始化6. 封装6.1 封装的概念6.2…
类和对象中4. this引用4.1 为什么要有this引用4.2 什么是this引用4.3 this引用的特性5. 对象的构造及初始化5.1 如何初始化对象5.2 构造方法构造器5.2.1 概念5.2.2 特性5.3 默认初始化5.4 就地初始化6. 封装6.1 封装的概念6.2 访问限定符6.3 封装扩展之包6.3.1 包的概念6.3.2 导入包中的类6.3.3 自定义包6.3.5 常见的包6.3.6 封装操作举例4. this引用
4.1 为什么要有this引用
先看一个日期类的例子
public class Date {public int year;public int month;public int day;public void setDay(int y, int m, int d){year y;month m;day d;}public void printDate(){System.out.println(year / month / day);}public static void main(String[] args) {// 构造三个日期类型的对象 d1 d2 d3Date d1 new Date();Date d2 new Date();Date d3 new Date();// 对d1d2d3的日期设置d1.setDay(2020,9,15);d2.setDay(2020,9,16);d3.setDay(2020,9,17);// 打印日期中的内容d1.printDate();d2.printDate();d3.printDate();}
}
//----------------
//打印
2020/9/15
2020/9/16
2020/9/17但是三个对象都在调用setDate和printDate函数但是这两个函数中没有任何有关对象的说明setDate和printDate函数如何知道打印的是那个对象的数据呢
其实在成员方法的第一个形参中默认隐藏了一个thisthis引用的是调用成员方法的对象。
4.2 什么是this引用
**this引用指向当前对象(成员方法运行时调用该成员方法的对象)在成员方法中所有成员变量的操作都是通过该引用去访问。**只不过所有的操作对用户是透明的即用户不需要来传递编译器自动完成。
public class Date {public int year;public int month;public int day;public void setDay(int year, int month, int day){this.year year;this.month month;this.day day;}public void printDate(){System.out.println(this.year / this.month / this.day);}
}注意this引用代表的是的是调用成员方法的对象。 每个成员方法括号中的第一个参数默认是this 注意我们要习惯使用this。 4.3 this引用的特性 this的类型对应类类型引用即哪个对象调用就是哪个对象的引用类型 this只能在成员方法中使用 在成员方法中this只能引用当前对象不能再引用其他对象 this是“成员方法”第一个隐藏的参数编译器会自动传递在成员方法执行时编译器会负责将调用成员方法 对象的引用传递给该成员方法this负责接收
5. 对象的构造及初始化
5.1 如何初始化对象
通过前面知识点的学习知道在Java方法内部定义一个局部变量时必须要初始化否则会编译失败。
public static void main(String[] args) {int a;System.out.println(a);
}
// Error:(26, 28) java: 可能尚未初始化变量a要让上述代码通过编译非常简单只需在正式使用a之前给a设置一个初始值即可。如果是对象
public class Date {public int year;public int month;public int day;public void setDay(int y, int m, int d){this.year y;this.month m;this.day d;}public void printDate(){System.out.println(year / month / day);}
}
public static void main(String[] args) {Date d new Date();d.printDate();d.setDate(2021,6,9);d.printDate();
}
// 代码可以正常通过编译需要调用之前写的SetDate方法才可以将具体的日期设置到对象中。通过上述例子发现两个问题
每次对象创建好后调用SetDate方法设置具体日期比较麻烦那对象如何快捷进行初始化呢局部变量必须要初始化才能使用为什么字段声明之后没有给值依然可以使用
这两个问题就涉及到了构造方法和默认初始化的问题。
5.2 构造方法构造器
5.2.1 概念
构造方法(也称为构造器)是一个特殊的成员方法名字必须与类名相同在创建对象时由编译器自动调用并且在整个对象的生命周期内只调用一次。
什么是构造方法
构造方法非常特殊这个方法没有返回值方法名和类名是一样的。
如果我们没有在类中写任何的构造方法那么Java会帮我们提供一个默认的不带参数的构造方法。
public class Date {public int year;public int month;public int day;public void setDay(int y, int m, int d){year y;month m;day d;}public void printDate(){System.out.println(year / month / day);}Date() {System.out.println(这个是构造方法,在实例化对象的时候就会进行调用);}////public static void main(String[] args) {Date date1 new Date();}
}
//--------------
//编译器运行结果为
//这个是构造方法,在实例化对象的时候就会进行调用当然在一个类中没有写构造方法的话Java会默认提供。
但是一个类当中写了构造方法的话java就不会提供了。
看看效果
public class Date {public int year;public int month;public int day;public void setDay(int y, int m, int d){year y;month m;day d;}public void printDate(){System.out.println(year / month / day);}public Date() {System.out.println(这个是构造方法,在实例化对象的时候就会进行调用);}public Date(int year ,int month ,int day) {this.year year;this.month month;this.day day;}////public static void main(String[] args) {Date date1 new Date(11,11,11);date1.printDate();}
}
//--------------
//编译器运行结果为
//11/11/11这样我们就可以通过构造方法在进行对象实例化的过程中进行成员变量的初始化。
至于我们写了两个Date函数那么这两个函数就属于重载关系
public Date() {System.out.println(这个是构造方法,在实例化对象的时候就会进行调用);
}
public Date(int year ,int month ,int day) {this.year year;this.month month;this.day day;
}重载方法名相同参数列表不同与返回值无关。
我们可以说当一个对象调用完构造函数那么这个对象就生成了。
因为生成一个对象分为两步1. 为对象分配内存 2. 调用合适的构造方法
补充 对于构造方法我们不能进行添加void因为如果添加了返回值的话那么就不属于我们的构造方法了。 如果自己没有写构造函数那么编译器会提供一个默认的不带任何参数的构造方法。
5.2.2 特性 名字必须与类名相同 没有返回值类型设置为void也不行 创建对象时由编译器自动调用并且在对象的生命周期内只调用一次(相当于人的出生每个人只能出生一次) 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法) 如果用户没有显式定义编译器会生成一份默认的构造方法生成的默认构造方法一定是无参的。一旦用户定义编译器则不再生成。 如果生成了一个带有参数的构造方法那么一定要在对象实例化的过程中进行传参否则会报错。 构造方法中可以通过this调用其他构造方法来简化代码 在这个过程中this代表的是调用当前对象的其他构造方法。 public class Date {public int year;public int month;public int day;public void printDate(){System.out.println(year / month / day);}public Date() {this(11,11,11);}public Date(int year ,int month ,int day) {this.year year;this.month month;this.day day;}public static void main(String[] args) {Date date1 new Date();date1.printDate();}
}
//------------
//编译器运行结果为
//11/11/11但是在调用其他构造方法的时候有一定的要求
那么就是this语句一定要放在构造方法中作为第一条语句。不然会报错。 只能在构造方法内部才能使用不能在其他方法中使用。 不能形成环否则进行反复调用构造函数形成封闭循环 绝大多数情况下构造函数使用public来修饰特殊场景下会被private修饰。
至于这个我们先不管以后会讲。
总结 this.date 访问当前对象的成员变量 this.func() 访问当前对象的成员方法 this() 调用当前对象的其他构造方法 this不能调用静态static修饰的成员方法和变量这个后面我们再说 5.3 默认初始化
为什么局部变量在使用时必须要初始化而成员变量可以不用呢
要搞清楚这个过程就需要知道 new 关键字背后所发生的一些事情
Date d new Date(2021,6,9);在程序层面只是简单的一条语句在JVM层面需要做好多事情下面简单介绍下 检测对象对应的类是否加载了如果没有加载则加载 为对象分配内存空间 处理并发安全问题 比如多个线程同时申请对象JVM要保证给对象分配的空间不冲突 初始化所分配的空间 即对象空间被申请好之后对象中包含的成员已经设置好了初始值比如
数据类型默认值byte0char‘\u0000’short0int0long0Lbooleanfalsefloat0.0fdouble0.0referencenull
设置对象头信息(关于对象内存模型后面会介绍)调用构造方法给对象中各个成员赋值
所以在调用构造函数进行初始化之前我们就会进行赋值为默认值。
补充
public只是权限的问题。只提一下
局部变量定义在方法内部的变量。
成员变量定义在类的内部的变量定义在成员方法的外部。
定义在成员方法内部的变量就叫做局部变量。 5.4 就地初始化
在声明成员变量时就对成员变量设置初始值。
public class Date {public int year 1900;public int month 1;public int day 1;//进行就地初始化public Date(){}public Date(int year, int month, int day) {}public static void main(String[] args) {Date d1 new Date(2021,6,9);Date d2 new Date();}
}当然这个除非是业务需求不然没有提别大的意义如果成员变量会进行修改那么就地初始化相当于进行了一个默认值的定义。
6. 封装
6.1 封装的概念
**面向对象程序三大特性封装、继承、多态。**而类和对象阶段主要研究的就是封装特性。
何为封装呢
简单来说就是套壳屏蔽细节。把类的实现细节进行隐藏对外只提供一些交互的接口。
封装将数据和操作数据的方法进行有机结合隐藏对象的属性和实现细节仅对外公开接口来和对象进行交互
比如对于电脑这样一个复杂的设备提供给用户的就只是开关机、通过键盘输入显示器USB插孔等让用户来和计算机进行交互完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
然而要进行封装就涉及到了访问限定符。
6.2 访问限定符
Java中主要通过类和访问权限来实现封装类可以将数据以及封装数据的方法结合在一起更符合人类对事物的认知而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符
private 默认权限 protected public
默认权限就是我们什么都没加的时候的使用默认权限访问限定符。
public class Date {int year;
}private
权限非常小被修饰之后只能在自己的类中进行使用。
class Student {public String name;public void show() {System.out.println(姓名 name);}
}默认权限default 只能在自己的包中进行使用 这就涉及到了包的概念如果不懂包是什么可以先跳过这块继续看下一块的内容。 protect和public以后再讲因为涉及到了子类的知识
6.3 封装扩展之包
6.3.1 包的概念
要了解封装就要了解权限要了解权限就要了解包。
在面向对象体系中提出了一个软件包的概念即为了更好的管理类把多个类收集在一起成为一组称为软件包。有点类似于目录。比如为了更好的管理电脑中的歌曲一种好的方式就是将相同属性的歌曲放在相同文件下也可以对某个文件夹下的音乐进行更详细的分类。 包就像文件夹一样一个文件夹当中不能有相同的文件名不同文件夹下可以有相同的文件名。
在Java中也引入了包包是对类、接口等的封装机制的体现是一种对类或者接口等的很好的组织方式比如一个包中的类不想被其他包中的类使用。包还有一个重要的作用在同一个工程中允许存在相同名称的类只要处在 不同的包中即可。
6.3.2 导入包中的类
Java 中已经提供了很多现成的类供我们使用. 例如Date类可以使用java.util.Arrays导入java.util这个包中的Arrays类.
public class Test {public static void main(String[] args) {int[] arr {1,2,3};java.util.Arrays.toString(arr);}
}但是这种方法比较麻烦我们可以使用import语句导入包
import java.util.Arrays; // 导包public class Test {public static void main(String[] args) {int[] arr {1,2,3};Arrays.toString(arr); }
}
如果需要使用java.util中的其他类, 可以使用import java.util.*
import java.util.*;
public class Test {public static void main(String[] args) {int[] arr {1,2,3};Arrays.toString(arr);}
}import java.util.*不是把里面的所有的类都导进来是随取随用。用到哪个类就会导哪个类。
但是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况. import java.util.*;
import java.sql.*;
public class Test {public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 这个时候编译器就不知道该导入哪个包了毕竟两个包中都有Date类所以编译出错Date date new Date();System.out.println(date.getTime());}
}
//--------------
// 编译出错
Error:(5, 9) java: 对Date的引用不明确java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配在这种情况下需要使用完整的类名
import java.util.*;
import java.sql.*;
public class Test {public static void main(String[] args) {java.util.Date date new java.util.Date();System.out.println(date.getTime());}
}使用import static可以导入包中静态的方法和字段 pow方法就是Math中的一个静态方法我们使用import static就可以进行简写在调用的时候只需要写方法名。
没有import static修饰过的
import java.lang.Math;
public class Test {public static void main(String[] args) {double x 10;double result Math.pow(x,2);}
}import static修饰过的
import static java.lang.Math.*;
public class Test {public static void main(String[] args) {double x 10;double result pow(x,2);}
}至于这个import static不建议大家使用
6.3.3 自定义包
包就是所谓的文件夹
操作步骤
在 IDEA 中先新建一个包: 右键 src - 新建 - 包 在弹出的对话框中输入包名,通常会用公司的域名的颠倒形式例利于域名是www.bit.com那么包的名字就是com.bit.www 在包中创建类, 右键包名 - 新建 - 类, 然后输入类名即可. 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句 package是声明当前类是在哪个包底下。
package com.bite.demo1;6.3.5 常见的包
java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。java.lang.reflect:java 反射编程包;java.net:进行网络编程开发包。java.sql:进行数据库开发的支持包。java.util:是java提供的工具程序包。(集合类等) 非常重要java.io:I/O编程开发包。
除了JDK自动导入的剩下的都需要我们用import自己导入
10.Java类和对象完作业继承
回顾
什么是类什么是对象什么是面向对象什么是面向过程
如何定义一个类
如何实例化一个对象
如果通过对象访问对象的成员属性、成员方法
通过对象.进行访问
this引用代表的是当前对象的引用
构造方法中的this引用可以访问成员变量可以访问成员方法也可以访问当前对象的其他构造方法
引用指向null代表什么代表这个引用不指向任何对象
引用不能指向引用但是引用能指向引用所指向的对象。
一个引用只能指向一个对象不能指向多个对象。
封装根据业务需求对类的细节进行隐藏提供公开的接口来和数据进行交互。6.3.6 封装操作举例
class Person {private String name;public int age;private void eat() {System.out.println(吃饭);}public void show() {System.out.println(name age);}
}我们通过private关键字进行对成员变量和成员方法进行封装private封装后的只能在类中使用。
name成员变量、eat成员方法都已经封装起来了
使用private关键字进行了封装。此时name的权限就变小了只能在当前类当中才能进行访问。 补充 public哪里都能访问 private只能在当前类访问 default只能在包中进行访问 在Java编译器当中我们对构造函数创建有快捷方法。
第一步右键选择Generate、或者快捷键AltInsert 第二步选择Constructor 第三步选择构造函数的形参多选按住CTRL 这样就可以在封装的情况下通过构造函数在对象实例化的过程中进行初始化成员变量。
但是如果想要更改姓名的话却无法更改除非再次进行实例化一个对象所以我们可以通过创建成员方法作为接口那么我们就创建了成员方法setName进行姓名的更改getName进行名字的查询
class Person {private String name;public int age;private void ear() {System.out.println(吃饭);}public void show() {System.out.println(name age);}public Person(String name, int age) {this.name name;this.age age;}public Person(String name) {this.name name;}public String getName() {return this.name;}public void setName(String name) {this.name name;}
}
public class Test {public static void main(String[] args) {Person person new Person(mengdehong,20);person.setName(meng);System.out.println(person.getName());person.show();}
}
//--------------
//编译器运行结果为
//meng
//meng 20但是我们有多个成员变量进行封装的时候我们都要对每个成员变量进行set变量、get变量的方法吗
实际上我们也有快捷操作。
第一步左键选择Generate 第二部选择Getter and Setter 第三步进行选择所需要创建成员方法的成员变量 这样就创建好了成员方法作为接口 今天我们讲了类和对象的一部分剩下的内容我们会在下一篇博客中讲完。