java基础——面向对象

一、面向过程与面向对象

一个最简单的例子:将大象放进冰箱,按照面向过程的方式来思考分为三步:打开冰箱,将大象放进冰箱,关闭冰箱。如果按照面向对象的方法来思考:冰箱是一个对象,我们调用的都是冰箱的功能,冰箱.打开,冰箱.存储,冰箱.关闭。这就是面向过程和面向对象的区分。

面向过程:先确定如何操作数据,再决定如何组织数据。面向对象:将数据放在第一位,然后再考虑操作数据的算法。

对于一些规模较小的问题,用面向过程的方法思考比较理想。而对于一些规模较大的问题,用面向对象的方法更为恰当。

二、类与对象的关系

类是对现实生活中事物的描述,是构造对象的模板。事物的描述一般包括:属性和行为,属性对应类中的变量,行为对应类中的方法。由类构造对象的过程称为创建类的实例,通过new关键字来完成类的生产。

三、成员变量和局部变量、匿名对象

成员变量和局部变量区别:(1)成员变量作用于整个类中,局部变量作用于函数中或语句中。

(2)在内存中的位置:成员变量存在于堆内存中,因为对象的存在才在内存中存在。它是具有默认值的。

局部变量存在于栈内存中,必须初始化才能参与运算。

匿名对象:假设有一个Car类,它有一个属性num,那么我们创建这个对象并调用它的num属性时,一般都这样调用:

Car c=new Car();      c.num=5;

还有另外一种调用方式:new Car().num=5;

第二种方式就是匿名对象调用方式,什么情况下才使用匿名对象?

1.当对对象的成员只调用一次时,可以用匿名对象来完成,这样写简单。如果对一个对象进行多个成员调用时,必须给这个对象起个名字

2.可以将匿名对象作为实际参数进行传递。

main(){     show(new Car());   }     

public static void show(Car c){......}

四、面向对象的特征

封装、继承、多态。

封装,也就是数据隐藏,将对象的属性和行为封装到一个包中,并对对象的使用者隐藏了数据的实现方式。

继承,通过扩展一个类来建立另外一个类的过程称为继承。

多态,事物存在的多种体现形态。在java中最基本的体现就是父类引用指向自己的子类对象。

五、封装

如何封装:通过一个关键字,private。隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:将变化隔离,便于使用,提高重用性,提高安全性。

注:函数本身就是一个较小的封装体,类是如此,包也是如此。

private:私有,权限修饰符,用于修饰类中的成员。

注:私有只在本类中有效。将成员私有化以后,类以外即使建立了对象也不能直接访问,这时如果要访问此成员,需要在类中提供对应的访问此成员的方式。一个成员变量通常对应两种方式:设置set和访问get。之所以对外提供访问方式,就因为可以在访问方式中加入逻辑判断等语句,对访问的数据进行操作,提高代码健壮性。

六、构造函数(类中的另一个成员)与构造代码块

构造函数

特点:函数名与类名相同,不需要定义返回值类型(和void不一样),不可以写return语句。对象一建立,就会调用与之对应的构造函数。

作用:可以用于给对象进行初始化。

注:一个类中可以有多个构造函数,构造函数属于函数的一种,具有函数的特性,包括重载。构造函数可以私有化,因为它属于类中的一个成员。

构造代码块

和构造函数的区别:构造代码块用于给所有对象进行统一初始化。构造函数是给相应的对象进行初始化。

定义时可以将不同对象的共性定义在构造代码块中执行。构造代码块也是对象一建立就开始运行。

七、this

class Person

{

private String name;

private int age;

Person(String name)

{

this.name=name;

}


Person(String n,int a)

{

name=n;

age=a;

}

}

this表面上看来是区分局部变量和成员变量。

this:代表本类对象,到底代表哪一个取决于它所在函数所在对象的引用,简单说,哪个对象在调用this所在的函数,this就代表哪个对象。就像:Person p=new Person("lisi");此时,this就代表p

this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,就用this来表示这个对象。但凡类功能内部使用了本类对象,都用this来表示。

总的来说this:(1)用于区分同名变量的情况(2)用于构造函数间调用(不能用于一般函数)

八、static

假如一个类需要被多次调用,而创建的这些对象都有共性数据,那么这些共性数据在类中就可以提取出来并用static修饰来完成,可以简化数据的流程。

用法:是一个修饰符,用于修饰类中成员。当成员被static修饰后,除了可以被对象调用外,还可以直接被类名调用。格式:类名.静态成员。

静态的特点:

(1)随着类的加载而加载(静态随着类的消失而消失,说明其生命周期最长)

(2)优先于对象存在

(3)被所有对象共享

(4)可以直接被类名所调用

静态使用注意事项:

(1)静态方法只能访问静态成员,非静态方法既可以访问静态成员,也可以访问非静态成员。(因为静态最先存在,就像人一样,死者不能调用生者)

(2)静态方法中不可以定义this,super关键字。因为静态方法优先于对象存在。

(3)主函数是静态的。主函数是一个特殊的函数,可以被JVM调用,作为程序的入口,程序的起始点。

关于主函数:

public:代表该函数的访问权限是最大的。

static:代表着主函数随着类的加载就已经存在

void:主函数没有具体的返回值。

main:不是关键字,但是是一个特殊的单词,可以被JVM识别

函数的参数:(String[] args):参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。

主函数是固定格式的,主函数是可以重载的,但是JVM只识别(String[] args)的主函数。args作为数组类型参数的名字,是可以改变的。既然JVM可以调用它,那么JVM必然给args传入了一个值,这个值是new String[0];当然,我们自己也可以传入其他值试一下,运行的时候可以 java MainDemo  haha heeh heihe ,这样运行的话,相当于把String[] args={haha,heeh,heihe};

静态的利弊:

利:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份,可以直接被类名调用。

弊:生命周期过长。访问出现局限性(静态虽好,只能访问静态)

什么时候使用静态?

从两方面下手:静态成员变量和静态成员函数。

当对象中的相同属性出现一样的数据时,该数据就可以被静态所修饰。

当功能内部没有访问到非静态数据时,则该功能可以被定义成静态的。

静态应用:每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便服用。

静态代码块

格式:static{静态代码块中的执行语句;}

特点:随着类的加载而执行,只执行一次。用于给类进行初始化。

九、静态代码块->构造代码块->构造函数、类加载运行、对象建立运行这几个过程要搞清。

十、对象初始化过程

class Person{

private String name;

...

Person(String name,int age)

{

this.name=name;

this.age=age;

}

.......

}

当new一个Person实例对象时,对象是这样进行初始化的。

(1)new用到了Person.class文件,先找到Person.class文件并加载到内存中

(2)执行该类中的static代码块,如果有的话,给Person.class类进行初始化

(3)在堆内存中开辟空间,分配内存地址

(4)在堆内存中建立对象的特有属性,并进行默认初始化

(5)对对象进行显示初始化,构造代码块初始化,构造函数初始化

(6)将内存地址付给栈内存中的对象的引用

十一、单例设计模式

设计模式:解决某一类问题最行之有效的办法。

java中共有23种设计模式。

单例设计模式:解决一个类在内存中只存在一个对象的情况。

目的:让A和B操作同一个对象,保证对象的唯一性。

分析:(1)为了避免其他程序过多地建立该对象,先禁止其他程序建立该对象。

(2)还为了让其他程序可以访问到该类对象,只好在本类中自定义一个本类对象。

(3)为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

代码体现:(1)构造函数私有化。

(2)在类中创建一个本类对象。(因为(3)提供的方法是静态的,所以此本类对象必须定义成静态的。)

(3)提供一个方法可以获取到该对象。(因为单例设计模式的构造函数私有化,外界不能创建对象调用此方法,所以只能定义成静态的,用类名直接调用。)


单例设计模式的另一种体现:懒汉式

class Single

{

       privatestatic Single s=null;

       privateSingle(){}

       publicstatic Single getInstance()

{

              s=new Single();

       return s;

}

}

注:开发一般使用饿汉式,因为安全简单。懒汉式如果被多个人所调用的话,就会出现问题。

十二、继承(extends)

通过扩展一个类来建立另外一个类的过程。(事物之间都是有关系的,继承只是这些关系中的一种。)好处:

(1)提高了代码的复用性。(2)继承让类与类之间产生了关系,有这这个关系才有了多态的特性。

弊端:打破了封装性。

注:千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承。就像猫,虎,豹子等都属于猫科动物。

继承的抽取原则:先有了对象,将对象用类表示出来,将类中的共性进行抽取从而产生父类。

java语言中只支持单继承,不支持多继承。为什么不支持多继承?因为多继承容易带来安全隐患,当多个父类中定义了相同的功能但功能内容不同时,子类继承后不确定要运行哪一个。但是java支持多层继承。

如何使用一个继承体系中的功能?答:查阅父类功能,创建子类对象使用功能。

子类实例化过程

在对子类对象进行初始化时,父类的构造函数也会运行,这是因为子类的构造函数默认第一行有一条隐式语句,叫super();这条隐式语句一定要在子类构造函数第一行,因为要先初始化父类,再初始化子类。这个super()语句会访问类中空参数的构造函数,当父类中没有空参数的构造函数时,需要在子类中手动指定要访问的构造函数。

为什么子类一定要访问父类中的构造函数?

因为父类中的数据子类可以直接获取,所以子类对象在建立时,要先看看父类是如何对这些数据进行初始化的。当父类中已经定义完了内容,子类可以直接调用。

十三、final

最终,作为一个修饰符存在。可以修饰类,变量,函数。

(1)被final修饰的类不可以被继承,为了避免被继承,防止子类复写其功能。

(2)被final修饰的变量是一个常量。只能赋值一次,既可以修饰成员变量,也可以修饰局部变量。

(3)被final修饰的方法不可以被复写。

final为什么存在?

当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便于阅读,而这个值不需要改变,所以加上final修饰。作为常量,常量的书写规范是所有字母大写,如果由多个单词组成,单词间通过“_”连接。

(4)内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。

十四、抽象类

当多个类中出现相同功能,但是功能主体不同时,这是可以进行向上抽取,只抽取功能定义,不抽取功能主体。(注:抽象类不能创建对象。)

特点:(1)抽象方法一定定义在抽象类中。

(2)抽象方法和抽象类都必须被abstract关键字修饰。

(3)抽象类不可以用new创建对象,因为调用抽象方法没有意义。

(4)抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法后由其子类创建对象调用,如果子类只复写了部分抽象方法,那么该子类还是抽象类。

注:抽象类中既可以有抽象方法,也可以由非抽象方法。

由此引出模板方法设计模式:一部分功能确定,一部分功能不确定,而确定的部分在调用不确定的部分,就将不确定的部分暴露出去,由该类的子类实现。

十五、接口

可以认为是一个特殊的抽象类。

当抽象类中的所有方法都是抽象的时,那么该类可以通过接口的方式来表示。用关键字interface

接口定义格式特点:(1)接口中常见定义:常量,抽象方法。(2)接口中的成员都有固定修饰符。(接口中的成员都是public的)

常量:public static final        方法:public abstract

注:接口与接口之间是继承关系,且支持多继承。

类与类继承:父类中有一些非抽象方法可以直接拿过来用。

类与接口实现:接口中的方法都是抽象的,不可以直接实例化,必须由子类全部实现后才可以去做这些事情。

接口的好处:接口可以被类多实现,也是对多继承不支持的转换形式。

接口的特点:(1)对外暴露了规则(2)提高了功能扩展性(3)降低了耦合性

简单一句话:接口就是为了扩展功能而存在。

十六、多态

事物存在的多种体现形态。如动物:猫,狗    一般实例化时: 猫 cat=new 猫(); 多态下: 动物 cat=new 猫();

(1)多态的基本体现:父类引用指向自己的子类对象。

(2)多态的前提:必须是类与类之间有关系,要么继承,要么接口实现

(3)多态的好处:大大提高了程序的扩展性,但是只能使用父类的引用访问父类中的成员。

(4)多态的应用:以前指挥一个对象去做事情,现在指挥一批对象去做事情,是因为找到了他们的共同点。

(5)多态使用时的注意事项:

十七、内部类,匿名内部类

1、内部类

(1)一个类定义在另一个类的里面,里面的那个类就被称为内部类。

(2)内部类的访问规则:内部类可以直接访问外部类中的成员,包括私有;外部类要访问内部类,必须建立内部类对象。

(3)为什么内部类能直接访问外部类中的成员?

因为内部类中持有一个外部类的引用。格式:外部类名.this

(4)当内部类定义在外部类的成员位置上时,而且非私有,可以在外部其他类中直接建立内部对象。

格式:外部类.内部类 变量名=外部类对象.内部类对象

(5)内部类可以被成员修饰符所修饰,因为它作为外部类的成员存在。

注:当内部类被静态修饰后,只能直接访问外部类中的静态成员,出现了访问局限性。

(6)为何定义内部类?当描述事物时,事物的内部还有事物,该事物就用内部类来描述,因为内部事物在使用外部事物的内容。

一个简单的内部类:

class Outer

{

private int num0=5;

class Inner()

{

private int num1=8;

public void printInner()

{

//System.out.println("num1="+num1);

System.out.println("num0="+num0);//此处之所以能访问外部类中的成员,是因为持有外部类中的引用。

}

}

public void showOuter()

{

Inner in=new Inner();

System.out.println("Inner num="+in.num);

}

}

(7)匿名内部类:就是内部类的简写格式。

定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。如下,我们一般都这样继承一个类,然后用这个子类创建对象:Inner in=new Inner();

class AbsDemo{....}

class Inner extends AbsDemo

{

void show()

{

System.out.println("show:"+x);

}

}

使用匿名内部类后:

new AbsDemo()

{

void show()

{

System.out.println("show:"+x);

}

}; ------------------------/就是这样创建对象。

匿名内部类格式:new 父类或者接口(){ 定义子类的内容 }

其实匿名内部类就是一个匿名子类对象,可以理解为内容具体化的对象。意义:简化书写,覆盖方法。

匿名内部类的局限性:当父类或者接口中的抽象方法过多时,匿名内部类的阅读性将会变差。一般情况下:匿名内部类中的方法最好不要超过3个。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值