前言:我是一名大一在读生,本这学期第一次接触Java语言的学习。我目前正处于初学阶段,学校在本周是第四次大课授课——类与对象。
个人初学心得 :在任何“正式” 内容还没接触时,(安装好编译器,配好环境变量),尝试照着敲一些基本的代码,尝试去理解别人写出来的每条语句大抵功能是什么,尝试先去接受。让自己的大脑对新知识别那么抗拒。这样在正在上课听老师授课的时候,会容易跟得上,能让自己快速进入状态。以下便是我根据自己对老师授课内容的理解和一些知识点,为了让我能更加理解掌握,做出的一个大致框架。
1.面向对象编程:在编程的学习中,我们会学到面向过程和面向对象两种编程思想。 现在所学的java便是面向对象编程(OOP)那么面向对象到底是什么呢?
(1)首先先简单说明一下面向过程,对于之前所学的c语言便是属于面向过程,既是对于某一问 题,将其分为不同的过程一 一来进行。比方说用新生报到为例 : 注册—缴费—分宿舍。
在面向过程的编程思想中,则是将新生报到这一事件分为以上四个过程,在代码的编写中 即一一通过函数将其分别写出来,执行完一个之后接着下一个。
(2)那么面向对象又是如何进行的呢?依旧以新生注册为例,但与上面所提到的步骤有所不同。 在面向对象中,我们将新生报到这一事件里所要进行的流程,对 “流程的主体” 分成多个类,从 而再进行相应的代码编写。
即注册—报名登记处;缴费—教务处;分宿舍—宿舍管理楼
(3)使用面向对象的好处是什么?——可重用性高,如何去理解?
用上面的例子来说,假如学校要创建学生系统(学籍信息的登记,教务处的学费缴纳,宿舍的分 配...),那么对面向过程来说,就要重新按上面的需求分过程再次编写代码;
而面向对象呢?只需要调用一下前面已经写好的类(登记处,教务处,宿舍管理楼),在相应的 地方加入需要的功能代码即可。
两者相比后者的代码重用性高很多,也可以节省我们的工作量,从而加快我们代码的书写速度。
2.包:资源管理机制,相当于我们计算机电脑中创建的 “文件档”
(1)之所以要创建包,是为了应对 出现相同类名 的情况,为了避免这种冲突,我们可以通过创 建一个package,从而对类进行管理;
(2)Java内置包:在Java在学习中,不仅我们自己可以创建包,系统同时也会提供内置包,既是 系统事先已经创建好的功能模块,当我们需要用到某一功能模块时,恰好系统有提供,那么我们 便可以直接调用相应的内置包。
常用的内置包可自行上网或翻阅书籍查找。
(3)包的访问:
格式:import 包名.类名;//单独导出某一个类
import 包名.*; //导入所有的包(节省了import语句)
3.类与对象:
Java程序是由多个类组成的。简单来说:类是抽象的,而对象是类的具体化例子。
举例来说,车是个抽象的类,而卡车·汽车·三轮车·自行车...这些有具体车型的就称为对象,是车的具体化例子。
(1)类的定义格式:
[访问修饰符] [类型修饰符] class <类名>{
[变量声明]
[方法定义]
}
(2)对象声明的创建格式:
a. 类名 对象句柄 = new 构造方法([参数表]);
【e.g Student s1 = new Student();】
b. 类名 对象句柄;
对象句柄 = new 构造方法(参数表);
【Student s1;s1 = new Student();】
(3)对象的使用格式:
对象名.成员变量;
对象名.成员方法([参数表]);
4.类体: 变量声明和方法定义
(1)变量声明
格式: [访问修饰符] [类型修饰符] <数据类型> <变量名> [=初始值] ;
命名规定 :小写的英文字母;名词性的单词命名;多个单词组成时第二个单词首字母大写
a.访问修饰符:
public: 公有访问权限 (任何包下的所有类都可以进行访问)
protected: 受保护的访问权限 (同一个包中类,和不同包中的子类,都可以访问该变量)
缺省: 包访问权限 (在同一个包在的类均可以访问)
private: 私有访问权限 (仅在变量当下的类可以访问使用,子类也不可以访问)
【一般情况下定义成员变量都会使用private访问修饰符,进行信息的隐藏,若要访问这些 私有变量,则需要通过相应的构造器进行访问】
b.类型修饰符——变量的分类:
缺省——实例变量,变量某一任何的类型修饰符
static——静态(类)变量,集体所有的
final——最终变量(常量),声明时要初始化赋值,声明赋值后不会再改变
c.成员变量:类体中所有的方法外定义出的变量
- 在整个类中有效;
- 使用前可以不显示初始化;(在构造器中初始化)(系统会初始化默认值)
【0:byte,int, short, long, float, double, char】
【null: 数组,类,接口,字符串】
- 不能在变量声明的语句后进行赋值;(如public int count; count=1;这种是错误的)
d.局部变量:类体中某一个方法内定义出的变量
- 只在所属的方法下有效;
- 使用前必须初始化;
- 能在变量声明的语句后进行赋值
(2)方法定义:对“对象”进行功能完善或状态的修改
格式: [访问修饰符] [类型修饰符] <返回类型> <方法名>(参数列表){ }
a.方法声明: 大括号前的部分
- 方法名:Java严格区分大小写;
首字母小写;多个单词组成时从第二个单词开始首字母要大写。
- 参数列表:参数的个数,类型与顺序。
- 返回类型:没有return语句就要用void。
b.方法体: 大括号内的部分
- 局部变量+合法的Java语句
【 ps补充:UML类图———“+”公有访问权限 “-”私有访问权限 “#”受保护访问权限】
c.方法的分类:
实例方法:即类型修饰符为缺省,只能被对象调用
静态方法:即类型修饰符为static,可以被类或者对象调用
最终方法:即类型修饰符为final,被对象调用,但子类不能对其进行修改
5.访问器和设置器:
使用访问器和设置器一般是针对 “ 其他类要访问私有数据 ” 的情况才会使用。
比如说定义了一个Student类和一个StudenTest类,在Student中定义了私有访问类型的name和number,但在StudenTest需要使用到这两个变量,那么就会在Studen类中事先为这两个变量创建好访问器和设置器。
于是,在StudenTest类中通过 对象名.setXxx(参数)设置器对相应的变量进行赋值,通过 对象名.getXxx()访问器对相应变量进行访问
(1)设置器:[访问修饰符] [void] setXxx(参数){}
- 访问修饰符只能用pubilc ,参数类型与变量类型一致
- 设置器有参数,没有返回值语句
public void setBookname(String bookname) {
this.bookname = bookname;
}
//setXxx(参数)为设置器的形式,有参数,但无需返回值,故添加void标注
//此处为什么使用关键词this,因为定义的参数与实例变量同名,为了方便系统的区分故使用this
//使用this调用成员变量,=左边是成员变量,=右边是局部变量
(2)访问器:[访问修饰符] [返回类型]getXxx(){return语句}
- 访问修饰符只能用pubilc ,返回类型与变量类型一致
- 访问器没有参数,有返回值语句
public String getBookname() {
return bookname;
}
//getXxx()为访问器的形式,括号内不需要携带参数,有返回值语句
6.构造方法 : 针对于新创建的对象,对新创建的对象进行初始化。当出现new关键字时,即开始调用相应的构造方法
(1)创建格式 : [访问修饰符] 类名 (参数列表){ 方法体 }
(2)构造方法的名字必须与所属的当下类名完全相同,没有返回值语句(void型)
(3)一个类中必须出现至少一个构造方法,但如果在类的定义中没有显示出来,那么系统会自动 为我们所定义的类创建一个缺省且没有参数和方法体的构造方法。
如果在类中显示出了构造方法,那么系统就不会提供。
(4)构造方法的参数可以是0(无参构造器),也可以是多个
(5)方法重载: 针对构造方法而言,即是方法名相同但参数列表不同的构造方法。
- 为什么会出现方法重载这一概念?即是我们也可以定义名字不同构造方法,但如果是在很多构造方法的情况下,那么我们在测试调用的时候会很不方便进行调用
- 在此,也许有人会有疑问,多个相同方法名的构造器,那么我们在测试调用的时候会不会搞混呢?放心,系统会高准确识别并调用的。
- 但也有一个地方需要注意,下面我以代码的形式展现出来
public Try(int age,String name){
this.age=age;
this.name=name;
}
public Try(int ages,String names){
this.ages=age;
this.names=name;
}
看似都符合了创建格式,但实际上当你在idea编写的时候,这一段代码是会报错的,虽然两个构造方法的参数表名字不同,但我们要知道,形参的名字是可以重复相同的,因此实际上这两个构造方法是同一种构造方法,不符合规定,重复了。
所以,上面所说的参数列表不同,就是指参数类型不同或者数量不同
7.对象的内存分配:
此部分通过几个变量对象来进行解释说明。
public class Student{
//定义一个变量和一个常量
int age;
String name;
Student c1=new Student();
int x=3;
int y=x;
x=4;
c2=c1;
int a[10];
a1=2;
String T="happy"
T="nohappy"
}
在程序中,系统会如何为以上所定义出来的变量,对象进行内存分配呢?在这里我们将会用到栈和堆这两个知识点:
(1)——a.对象c1,系统会在栈和堆中为其分配一个空间,在栈的空间中存放的是一个地址,而这 个地址 则会指向堆中的相应空间,空间里面便会存放着变量age和name;
b.当定义了一个新的对象c2,令其等于c1。那么同理,系统依旧会在栈中为其分配一个存 放着与c1相同的地址,共同指向堆中的相应空间;
c.当通过对象引用变量,对其进行赋值变化时,即c1.name=“小白”,那么相应的,c1和c2 指向的那个堆空间,里面的变量值也会相应发生改变;
d.当栈中没有变量指向堆中的某一空间时,在Java中系统会自动将其当作垃圾进行清理。
(2)——a.常量x,系统会为其在栈中划分一个空间,而空间里面存放的就是x的值;
b.当定义了一个变量y=x, 那么栈中也会划分出一个空间,存放的内容就是x的值;
c.当x的值发生变化,y的值依旧不变。
(3)——a.当定义的是一个数组时,那么数组的栈空间存放的则是一个地址,这个地址指向数组的 堆空间,堆空间里存放着a[0]—a[9]个元素;
b.倘若对其的某一个元素单独进行赋值,那么系统会为这个元素在栈中单独开出一个空 间,空间内存放的则是元素的值。
(4)——a.当定义出来的变量是一个已经初始化的字符串变量,那么系统会为其的栈空间存放一个 地址,但此时这个地址就不像之前那样指向的是某一个堆空间,它指向的是一个“常量池”
b.当这个变量的值发生改变时,在常量池中,并不是在原有的值上进行抹除重新填入,而 是另外单独开出一个空间,存放新的赋值,这一点与上面所提到的对象改变有所不同
针对以上,有一个大致的图形如下(方便理解):