Java面向对象--01
OOP基本概念 匿名对象 封装构造函数 this关键字
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. 面向对象的基本概念
1). 面相对象 (OOP) 和面向过程(OPP) 的关系
(1). 面相对象是把以前需要逐个执行的动作都全部封装起来
(2). 面向对象是基于面向过程的!!!!!
2). 面向对象的三大特征
封装、继承和多态
3). 类和对象
(1).基本概念
[1]. 类是对现实生活中事物的描述。
[2]. 对象是这类事物实实在在的一个个体
[3]. 类和对象在Java中的体现
{1}.在Java中描述事物就是用class来定义类
{2}.在Java中产生一个类的实体就是用new来创建类的对象
[4]. 描述事物和Java中类的关系
{1}.描述事物就是在描述事物的属性和行为
{2}.定义类就是在描述事物,就是在定义事物的属性和行为
(2). 类的成员
类中的属性和行为共同组成了类中的成员
(3). 局部变量和成员变量的区别
从内存中的位置和作用范围两个方面来考虑
[1]. 内存中的位置:成员变量位于堆内存中 (因为对象是存储在堆内存中的)
局部变量位于栈内存中
[2]. 作用范围:成员变量作用于整个类中 局部变量作用于函数体或者局部代码块中
4). 匿名对象
(1). 匿名对象与普通对象的关系
[1]. 对象可以有名字,也可以没有名字。没有对象名的对象就是匿名对象。
[2]. 匿名对象是普通对象的简化形式。
(2). 匿名对象对属性和方法的调用
[1]. 匿名对象直接调用属性是没有意义的!!
原因就是匿名对象没有名字,也就是没有引用变量在栈内存中直接指向堆内存中的匿名对象。因此 new Car(). num =5;执行完之后,匿名对象就变成了垃圾,会被回收掉。那么对其属性的读写操作也就没有什么意义了。
[2]. 匿名对象直接调用方法是有意义的!!
(3). 匿名对象的适用范围
[1]. 当对象的方法仅被调用一次的时候,可以使用匿名对象来简化书写。
匿名对象的弊端:但是如果对一个对象的多个成员进行调用的时候,匿名对象失去作用。
[2]. 可以将匿名对象作为实参进行参数传递。
注意:当这个被调用的方法接受一个匿名对象并且执行完毕之后,这个堆内存中的匿名对象就变成了垃圾对象。
5). 封装
(1). 含义
[1]. 是指隐藏对象的属性和实现细节,仅仅对外提供公共访问接口。
[2].对外提供公共访问接口的原因就是:在访问方式中加入逻辑判断语句
(2). 封装和私有的关系
[1]. 私有仅仅为封装的一种表现形式
[2]. 不私有同样也能实现封装。只要权限在你访问不到的权限的范围内,对你来说就是封装。
(3). 封装的原则
[1]. 将不需要对外提供访问的内容隐藏起来
[2]. 把属性都隐藏,提供公共方法对属性进行带有逻辑判断的访问。
6). 构造函数
(1). 构造函数的特点:
[1]. 函数名和类名相同
[2]. 没有返回值类型 (根本没有return语句)
[3]. 没有返回值类型和void的区别
{1}.void 是一种返回值类型。代表没有具体结果
{2}.无返回类型:根本不需要返回类型
[4]. 构造函数只能用来跟在new之后初始化对象,而不能像普通方法那样被调用!!!!
(2). 构造函数被调用的时机
对象一建立,就会调用与之对应的构造函数。
(3). 构造函数的作用
给对象进行初始化 (也就是为对象的某些属性进行赋值使得对象一产生就具备某些特征)
(4). 构造函数的小细节
[1]. 一个类中没有显式定义构造函数的时候,OS就会给该类加入一个空参的构造函数。
[2]. 如果一个类显式定义了一个构造函数,那么OS便不会给这个类在自动加入一个空参数的构造函数了。
(5). 构造函数和普通函数的区别
[1]. 写法上不同
[2]. 运行上不同
{1}构造函数在对象一建立的时候,就来给对象进行初始化的。
{2}只有对象调用才执行
【【再次强调!!!构造函数只能用来跟在new之后初始化对象,而不能像普通方法那样被调用!!!!】】
[3]. 执行的次数
{1}构造函数用来给对象进行初始化,所以仅仅运行一次;
{2}普通的方法可以被对象多次调用,可以执行多次
(6). 何时定义构造函数
当事物一存在的时候,就具备某些特性或行为的时候,就为这个类定义构造函数,将这些对象与生俱来的特性和行为封装到构造函数中去进行初始化
7). 构造代码块
很多时候,函数和代码块是相对应的。方法有自己的名字,而代码块却没有。
(1). 构造代码块的写法与目的:
[1]. 构造代码块的写法:用一对{}封装起来一段代码,并把这个代码块放在类的成员的位置上。这样的代码块就是构造代码块。
[2]. 构造代码块,顾名思义,也是起到构造方法的作用的代码块,也是给对象进行初始化。
(2). 构造代码块和构造函数的区别
[1]. 初始化对象的方面不同:
{1}.构造代码块是对这个类所有的对象进行进行共性的初始化。
{2}.构造函数可以指定。所以构造函数是对指定对象进行个性的初始化
[2]. 执行的顺序不同:构造代码块先于构造函数执行。
举例说明:(面试题)
class Person{
private String name;
private int age;
//构造代码块
{
name ="Benjamin";
age = 18;
System.out.println("Person code run....");
}
Person(){
System.out.println("name ="+ name+", age="+age);
}
Person(Stringname, int age){
this.name =name;
this.age =age;
System.out.println("name ="+ name+", age ="+age);
}
}
public class testtt {
public static void main(String[] args) {
Personp1 =new Person();//调用空参数构造函数进行初始化
Personp2 =new Person("zxm", 28);//调用非参数构造函数进行初始化
/*
* 两个Person对象,分别指定用不同的构造函数进行初始化。个性的初始化
* 但是,在每一个构造函数运行之前,构造代码块都对这两个对象进行统一的共性初始化
*/
}
}
运行结果:
8). this关键字
(1). this关键字指代谁?
this代表他所在函数所属的对象(指的是调用这个函数的对象)的引用变量。
****也就是哪个对象调用this所在的函数,this就代表哪个对象。
(2). 为什么类之间的非静态成员可以相互调用??
非静态成员要使用必须带上所属的对象才能使用。所以相互调用的时候,一定是通过this对象来完成的。这个this很多时候可以省略掉。
e.g.
class Person{
private String name;
private int age;
//非静态的speak方法调用了非静态的属性 name和 age
public void speak(){
System.out.println("name ="+ name+", age="+age);
}
//非静态的show()方法调用了非静态的方法speak()
public void show(){
speak();
}
}
在这里面,成员方法speak()调用了成员变量name和age,但是这里面name跟age都是非静态的成员,所以这两个成员的调用必须依赖某个对象。这个对象就是调用speak方法的对象。在speak方法中表示为this。这样,调用的name和age也就是调用了这个对象的name和age。所以:上面的speak方法相当于
public void speak(){
System.out.println("name ="+ this.name+", age ="+ this.age);
}
【个人理解】由于在某个对象的speak中调用了name和age,name和age前面都省略了调用这些属性的对象,所以这个对象就调用speak的对象,在speak方法内部表示成为this。
同样道理,上面的show相当于:
public void show(){
this.speak();
}
【个人总结】
{1}. 一旦在某个非静态方法中调用了另一个非静态的成员属性/方法(这就是非静态成员之间的相互调用),这个非静态的成员属性/方法前面必须跟上一个对象。
{2}. 如果没有跟对象来调用这个属性/方法,那么调用这个属性/方法的对象一定是和调用这个非静态方法的对象同为一个对象--àthis
一句话:非静态方法/变量要使用一定离不开相对应的对象来调用他们,否则无法使用!!!!
【类中的非静态成员被使用,全部由对象调用来完成。本类对象用this来表示】
(3). this的基本应用
[1]. 当定义类的功能的时候,如果一个方法的内部要用到调用该方法对象的时候,这是可以使用this表示这个对象。
e.g. 需求给Person类定义一个用于比较年龄是否相同的功能。
错误做法:X
public boolean compare(Person p1, Person p2){
if(p1.age == p2.age)
return true;
return false;
}
错误原因:这是Person类的compare功能可以比较另外两个人的年龄是否相同。但是需求是比较外来一个人和自己的年龄是否相同。所以 要在调用compare方法的内部引用到调用这个方法的对象自身,要使用this来表示。
public boolean compare(Person p){
if(this.age == p.age)
return true;
return false;
}
[2]. this在构造方法中的应用**
**(背景)需求:优化下面一个类的两个构造方法。
class Person{
private String name;
public int age;
Person(){
this.name =name;
System.out.println("name ="+ name+", age="+age);
}
Person(Stringname, int age){
this.name =name;
System.out.println("name ="+ name+", age ="+age);
this.age =age;
}
}
{1}. 错误做法:将构造方法作为普通方法调用。
class Person{
private Stringname;
public int age;
Person(Stringname){
this.name =name;
System.out.println("name ="+name+", age="+age);
}
Person(Stringname, int age){
Person(name); X!!
this.age =age;
}
}
【个人总结】
构造函数只能用来跟在new之后初始化对象,而不能像普通方法那样被调用!!!!所以,这里面按照非静态成员之间相互调用的观点来看:Person()的使用一定是存在对象调用它才可以的。由于没有写,那么就是this来调用,this.Person()。这样违背了构造函数不能被调用的原则!!所以错误。为了解决构造方法之间重用的问题,使用this语句来解决这样的问题。
解决办法:this(name)来替代Person(name)
{1}.this语句:
this以方法名的形式出现的时候,this(实参列表),称为this语句。是用来进行构造方法重用而设计的!!
注意:在一个构造方法中使用this语句的时候,不是再次创建一个对象,而是调用相应构造方法中的内容(实现代码重用)。是否进行实例化要看构造方法被调用的时候前面有没有new出现。只有new关键字+构造方法出现了,才能实例化对象。
this语句一定要放在构造方法的第一行!!!
***this语句必须放在另一个构造方法的第一行的原因:
【个人理解】this语句本身代表参数相对应的构造函数。构造函数的目的就是初始化对象。一个构造方法中又一次调用了this语句,那么说明这个构造的时候,要执行更细微的对象初始化工作。所以一定要先执行!!!
{2}.this关键字:
This以对象的形式出现的时候,就是关键字,this.成员,称为this关键字。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------