面向对象、继承、接口、抽象类
来源:互联网 发布:软件解决方案模板 编辑:程序博客网 时间:2024/05/02 02:33
一.面向对象
1.面向对象与面向过程的区别:
(1)面向过程强调功能
(2)面向对象强调具有功能的对象
举例:面向过程:打开冰箱——>把大象装进冰箱——>关闭冰箱;面向对象的思想就是强调具有功能的对象:冰箱打开,冰箱存储,冰箱关闭。
面向对象是一种思想,万物皆对象,程序是对象的集合,他们通过发送消息来告诉彼此所要做的;每个对象都有自己的由其他对象所构成的存储,这样可以构建复杂的体系,同时将复杂性隐藏在对象的简单性背后;每个对象都拥有其类型,每个类区别于其他类的特性就是可以发送什么消息给它。某一特定类型的所有对象都可以接受同样的信息,性质相同的事物可以交互。(java in thinking 抄的,哈哈哈!)
简单的说,面向对象的特点:1. 是一种解决问题的思想
2. 可以将复杂的事情简单化
3.将程序员从执行者转换成了指挥者
4. 完成需求时:
a)先要去找具有所需的功能的对象来用。
b) 如果该对象不存在,那么创建一个具有所需功能的对象。
c) 这样简化开发并提高复用。
2.面向对象三个特征:
封装,继承,多态
开发就是找对象,使用,没有对象,就创建一个对象
简单的说就是找对象,建立对象,使用对象,维护对象的关系
3.类和对象的关系:
现实生活中的对象,张三,李四
想要描述:提取对象中共性内容,对具体的抽象
描述时:这些对象的共性有:姓名,年龄,性别,学习java的功能
映射到java中就是class定义的类
具体对象就是对应java在堆内存中用java建立的实体;
类就是对现实生活中事物的描述。
对象就是这类事物实实在在存在。
对于计算机语言是先有类的个体
对于现实生活是先有对象
需求:描述汽车(颜色、轮胎数),描述事物其实就是在描述事物的属性和行为;
属性对应是类中的变量,行为对应的类中的函数(方法)
其实定义类,就是描述事物,就是定义属性和行为,属性和行为共同称为类中的成员变量和成员方法(函数)
4.成员变量和局部变量的区别:
(1).成员变量定义在类中,整个类中都可以访问。
局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
(2).成员变量存在于堆内存的对象中。
局部变量存在于栈内存的方法中。
(3).成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
(4).成员变量都有默认初始化值。
局部变量没有默认初始化值。
public class Car {//描述颜色String color = "红色";//描述轮胎数int num = 4; //运行行为void run() {System.out.println(color+"...."+num);}public static void main(String[] args){//生产汽车,在java中通过new操作符来完成;//其实就是在堆内存产生一个实体Car c = new Car();//c就是一个类类型变量类类型变量指向 对象//将已有的车的颜色改成蓝色,指挥该对象来做,在java中指挥//方式是:对象.对象成员c.color= "blue";c.run();new Car().run();/* 匿名对象(一次性使用)调用属性没意义;1.匿名对象使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化,如果对一个对象进行多个成员调用,必须给这个对象起个名字。2.匿名对象使用方式二:可以将匿名对象作为实际参数进行传递;*///需求:汽车装配厂,对汽车进行改造,将来的车能够改成黑车,//三个轮胎show(new Car());}public static void show(Car c) {c.num = 3;c.color ="black";c.run();}}</span></span></span>
二、对象的封装
1.对象封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式
2.好处:将变化隔离
便于使用;
提高重用性
提高安全性
3.封装原则:
(1)将不需要对外提供的内容都隐藏起来
(2)把属性都隐藏,提供公共访问方法对其访问;
4.封装的表现形式举例
如private:私有权限修饰符:用于修饰类中的成员(成员变量,成员函数),私有只在本类中有效;
注意:内存的分析,对于set方法的分析;
三、构造函数
1.构造函数的作用:可以用于给对象进行初始化
对象一建立,就会调用与之对应的构造函数;
2.构造函数小细节:
(1)当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数;
(2)当在类中自定义了构造函数后,默认的构造函数就没有了
3.构造函数与一般函数不同
(1)在写法上有不同
(2) 在运行上不同;
a.构造函数是在对象一建立就运行,给对象初始化;
而一般函数是对象调用时才执行,给是对象添加对象具备的功能;
b.一个对象建立,构造函数只运行一次;
而一般方法可以被该对象调用多次;
4.什么时候定义构造函数?
分析事物时,该事物存在具备一些特性或行为,那么将这些内容定义在构造函数中;
5.构造代码块:
作用:给对象进行初始化;
对象一建立就运行,而且优先于构造函数执行;
和构造函数的区别:
构造代码块是给所有对象进行统一初始化;
而构造函数是给对应的对象初始化;
注意:构造代码块中定义的是不同对象共性的初始化内容。
四、this关键字
1 .对this的简单认识:
this.看上去,是用于区别局部变量和成员变量同名情况
this为什么可以解决这个问题;
this到底代表的是什么?
this代表它所在函数所属对象的引用;
简单说,那个对象在调用this所在的函数,this就代表哪个对象
2.this的应用:
(1)当定义类中功能(函数)时,该函数内部要用到调用该函数的对象时,这是用this来表示这个对象;
但凡本类功能内部调用本类对象时,就用this,一般省略不写
(2)this语句:用于构造函数之间互相调用;
this语句只能定义在构造函数的第一行,因为初始化要先执行;
五、static的用法
1.用法:
(1).是一个修饰符,用于修饰成员(成员变量,成员函数);
(2).当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以被类名调用 类名.静态成员
2.特点:
(1).随着类的加载而加载,随着类的消失而消失,说明它的生命周期最长
(2).优先于对象存在;
明确一点:静态是先存在,对象是后存在的;
(3).被所有对象所共享;
(4).可以直接被类名所调用;
3.什么时候使用static?
要从两方面入手:
(1).当成员变量的数据各个对象都相同时,可以用static修饰,让多个对象共享。
(2).函数如果访问了特有数据(非静态成员变量),该函数是非静态的。
函数如果没有访问特有数据,那么该函数就可以静态修饰。
如果类中的功能都是静态的,那么该类创建对象是没有意义的,所以构造函数需要私有化。
因为静态修饰的内容有成员变量和函数;
什么时候定义静态变量(类变量)呢?
当对象的出现共享数据时,该数据被静态所修饰;
对象中的特有数据要定义成非静态存在于堆内存中
什么时候用?
看是否被多个对象使用,static比较耗内存;不建议大量使用;
4.静态使用注意事项:
(1).静态方法只能访问静态成员,非静态方法既可以可以访问静态也可以访问非静态;
(2).静态方法不可以定义this,super关键字
因为静态优先与对象存在,所以静态方法中不可以出现this
5.静态有利有弊:
利:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份,可以直接被类名调用。
弊端:生命周期过长,访问出现局限性;静态虽好,只能访问静态;六、实例变量和类变量
1.区别:
(1).存放位置;
类变量随着类的加载而存在于方法区中;
实例变量随着对象的建立而存在于堆内存中;
(2).生命周期:
类变量生命周期最长,随着类的消失而消失;
实例变量生命周期随着对象的消失而消失;
(3).主函数是静态的;
七、主函数:是一个特殊的函数,作为程序的入口,可以被jvm调用;
1.主函数的定义:
public代表者该函数访问权限是最大的;
static:代表主函数随着类的加载就已经存在了
void:主函数没有具体的返回值;
main:不是关键字;但是是一个特殊的单词,可以被jvm识别;
函数的参数:(String[] arg)函数的参数,参数类型是一个数组,该数组的元素师字符串,字符串类型的数组;
主函数是固定格式的,jvm识别;
jvm在调用主函数时,传入的是new String[0]
2.什么时候定义静态函数?
当功能内部没有访问到非静态数据(对象的特有数据)
那么该功能可以定义成静态的;
3.代码块。
(1).局部代码快。
对局部变量的生命周期进行控制。
(2).构造代码块。
对所有对象进行初始化。
(3).静态代码块。
对类进行初始化。
静态代码块:
格式:
static {
静态代码块的执行语句;
}
特点:随着类的加载而执行,只执行一次;用于给类进行初始化的;
八、单例设计模式:
1解决的问题:保证类在内存的对象唯一性。
想要保证对象唯一:
1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象
2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象;
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式;
代码体现:
1.将构造函数私有化;
2.在类中创建一个本类对象;
3.提供一个方法可以获取到该对象;
对于事物该怎么描述,还怎么描述。
当需要将该事物的对象保证在内存中唯一时,就将以上三步加上即可。
class Single {private Single(){}private static Single s = new Single();public static Single getInstance() {return s;}}public class SingleDemo {public static void main(String[] args) {Single s = Single.getInstance();System.out.println(s);}}</span>
2.两种方式的区别?
1.饿汉式:
single类一进内,就已经创建好了对象
public class Single {private static Single s = new Single();private Single() {}public static Single getInstance() {return s;}}</span>2.懒汉式(延迟加载方式):对象是方法被调用时,才初始化,也叫做对象的延时加载;
single类进内存,对象还没有存在,只有调用getIstance方法时,才建立对象;
package day01;class Single {private static Single s = null;private Single() {}public static Single getInstance() {if(s==null) s = new Single();return s;}}
开发时用饿汉式;
一、继承
1.意思:当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再重复定义这些属性和行为,只要继那个类即可。
2.举例:将学生和工人的共性的内容抽取出来,单独进行描述;
只要让学生和工人与单独描述的这个类有关系就可以了
3.特点:
(1).提高了代码的复用性;
(2).让类与类之间产生了关系,有了这个关系,才有了多态的特性;
注意:继承是所属关系;不要乱继承;千万不要为了获取其他类的功能,简化代码而继承;必须是类与类占有所属关系才可以继承,所属关系is a;
4.应用
如何使用一个继承体系中的功能;
想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能。那么这个体系已经可以基本使用;
那么在具体调用时,要创建最子类的对象,为什么呢:
一是因为有可能父类不能创建对象,
二是创建子类对象可以使用更多的功能,包括基本的也包括特有的;
简单一句话:查阅父类功能,创建子类对象使用功能;
举例:
//将学生和工人的共性的内容抽取出来,单独描述成一个类,只要他们继承这个类就可以了,提高代码的复用性class Person{//共同属性String name;int age;//person类对象初始化Person(String name,int age){this.name=name;this.age=age;}}class Student extends Person{//student对象初始化Student(String name,int age){super(name,age);}//子类特有行为void study(){System.out.println("good study");}class Worker extends Person{//worker对象初始化Worker(String name,int age){super(name,age);}//子类特有行为void work(){System.out.println("good work");}}}public class ExtendsDemo {public static void main(String[] args) {Student s = new Student("lisi",20);s.study();}}
5.子父类出现后,类成员的特点:
类中成员:
a.变量;
b.函数;
c.构造函数;
(1).变量:
如果子类中出现非私有的同名变量时,子类要访问本类中的变量,用this,子类要访问父类中的同名变量,用super;
super是的使用和this的使用几乎一致;
this代表的是本类对象的引用。
super代表的是父类对象的引用;
(2).子类中的函数
当子类出现和父类一模一样的函数时,
当子类对象使用函数,会运行子类函数的内容。
如同父类的函数被覆盖一样。
这种情况是函数的另一个特性:重写(覆盖)
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容;
(3)覆盖:
a.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败;
b静态只能覆盖静态;
记住:
重载:只看同名函数的参数列表;
重写:子父类方法要一模一样,包括返回值类型;(在多态中返回值子父类可以不一样,后面再说;)
(4).子父类中的构造函数
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句super();
super()会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();
注意:为什么子类一定要访问父类中的构造函数。
因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的;
所以子类在对象初始化时,要先访问一下父类中的构造函数;
注意:为什么完成这个必须的动作,就在子类的构造函数中加入了super()语句?
如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中哪个构造函数。同时子类构造函数中如果使用this调用了本类构造函数时,那么super就没有了,因为super和this都只能定义第一行。所以只能有一个。
但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。
注意:super语句一定定义在子类构造函数的第一行;
6.子类的实例化过程:
结论:
子类的所有构造函数,默认都会访问父类中空参数的构造函数;因为子类每一个构造函数内的第一行都有一句隐式super();
当父类中没有空参数的构造函数时,子类必须手动通过super或this语句形式来指定要访问父类的构造函数;
当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
父类中构造函数也有super,object是所有类的父类(上帝类);
为什么super和this不能再同一行?
因为他们都只能写在第一行,
为什么写在第一行?
因为初始化动作要先做;
7.final:最终。作为一个修饰符;
(1).可以修饰类,函数,变量。
(2).被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。(弥补了继承打破了封装性的弊端)
(3).被final修饰的方法不可以被复写。
(4).被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都会给这些值起个名字。方便与阅读。而这个值不需要改变,所以加上final修饰;
写法规范:常量所有字母都大写,多个单词,中间用_连接。
(5).内部类定义在类中的局部位置上,只能访问该局部被final修饰的局部变量
小想法:一个新的东西有好处,也有弊端,应尽量利用好处,减少弊端;
8.一个对象实例化过程:
Person p = new Person();
(1)JVM会读取指定的路径下的Person.class文件,并加载进内存,
并会先加载Person的父类(如果有直接的父类的情况下).
(2)在堆内存中的开辟空间,分配地址。
(3)并在对象空间中,对对象中的属性进行默认初始化。
(4)调用对应的构造函数进行初始化。
(5)在构造函数中,第一行会先到调用父类中构造函数进行初始化。
(6)父类初始化完毕后,在对子类的属性进行显示初始化。
(7)在进行子类构造函数的特定初始化。
(8)初始化完毕后,将地址值赋值给引用变量.
二、抽象类
1.定义:当多个类中出现相同功能,但是功能主体不同;这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体;
抽象:看不懂,模糊的,不具体的,不能创建一个看不懂的类的对象,因为调用方法没意义,如果方法加上括号就可以了;
2.抽象类的特点:
(1).抽象方法一定在抽象类中;
(2).抽象方法和抽象类都必须被abstract关键字修饰;
(3).抽象类不可以用new创建对象,因为调用抽象方法没意义;
(4).抽象类中的方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用;如果只覆盖部分抽象方法,那么该子类还是一个抽象类;(抽象类的抽取是分析问题来的,不是单纯抽取代码)
注意:抽象类可以强制子类做一些事情;
抽象类和一般类没有太大的不同,该怎么样描述事物,就如何描述事物;只不过该事物中,出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体;
通过抽象方法来表示。凡是不确定的,沿袭到子类来确定;
抽象类比一般方法多了个抽象函数,就是在类中可以定义抽象方法;
抽象类不可以实例化;
特殊:抽象类中也可以不定义抽象方法,这样做仅仅是不让该类建立对象;
3.抽象类举例:
假如我们在开发一个系统时,需要对员工进行建模,员工包含3个属性;姓名、工号、及工资。经理也是员工,除了含有员工的属性外,另外还有一个奖金属性,请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问;
员工类:name id pay
经理类:继承了员工,并有自己的bonus。
抽象类就是对某一些事物描述的时候,有些地方描述不具体,描述不了。
package day02;abstract class Employee{//定义变量;private String name;private String id;private double pay;//初始化;Employee(String name,String id,double pay) {this.name = name;this.id = id;this.pay = pay;}//行为public abstract void work();//强制子类必须工作,但工作具体内容以具体情况为准;}class Manager extends Employee{private int bonus;Manager(String name,String id,double pay,int bonus){super(name,id,pay);this.bonus = bonus;}// 子类自己的工作方式public void work() {System.out.println("manager work");}}public class AbstractDemo {public static void main(String[] args) {new Manager("lisi", "101", 2000, 500).work();}}
4.模板方法模式
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减;
获取时间:System.currentTimeMillis();
当代码完成优化后,就可以解决这类问题;这种方式模板方法设计模式;
什么是模板方法呢:
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分;那么这时就将不确定的部分暴露出去,由该类的子类去完成;
class GetTime(0 {//final关键字不让子类覆盖;public final getTime(){long start = System.currentIimeMillis();runCode();long end = System.currentIimeMillis();System.out.print("毫秒:"+(end-start));}public abstract void runCode();}class SubTime extends GetIime {public void runCode(){for(int i=0;i<10000;i++){System.out.println(i);}}}class TemplateDemo{public static void main(String[] args){SubTime gt = new SubTime();gt.getTime();}}
三、接口
1.接口:初期理解;可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示;
class用于定义类
interface用于定义接口;
2.接口常见定义格式特点:
(1).接口中常见定义:常量,抽象方法。
(2).接口中的成员都有固定修饰符;
常量:public static final
方法:public abstract
记住:接口中的成员都是public的;
接口:是不可以创建对象的,因为有抽象方法;
需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化;否则子类是一个抽象类;
接口中子类与父类的修饰权限必须相同,而抽象类中可以不相同;
接口可以被类多实现,也是对多继承不支持的转化形式;
类与类之间是继承关系,类与接口直接是实现关系。接口之间是继承关系;
3.接口的特点:
(1).接口是对外暴露的规则;
(2).接口是程序的功能扩展;
(3).接口可以多实现;
(4).类与类之间是继承关系,类与接口直接是实现关系,类可以在继承一个类的同时实现多个接口,接口之间是继承关系(java支持多继承,只有在接口中体现,类中是通过接口的实现);
4.抽象类和接口的异同点:
相同点:
都是不断向上抽取而来的。
不同点:
(1)抽象类需要被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
(2)抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。
接口中只能定义抽象方法,必须由子类去实现。
(3)抽象类的继承,是is a关系,在定义该体系的基本共性内容。
接口的实现是 like a 关系,在定义体系额外功能。
举例:
abstract class Sporter
{
abstract void play();//抽象类基本功能
}
interface Study//接口额外功能;
{
}
class wangwu extends Sporter implentments Study
{
}
package day02;//抽象学生类abstract class College{//学生肯定都学习和睡觉,但吸烟就不是必须的,只是额外的//抽象的学习方法abstract void study();//非抽象的睡觉方法void sleep(){System.out.println("sleep");}}//接口interface Smoking{void smoke();//定义额外的功能}//lisi有吸烟的嗜好,,但也要学习,实现吸烟接口class Lisi extends College implements Smoking{//复写学习方法void study(){System.out.println("Lisi_study");}//复写吸烟方法public void smoke(){System.out.println("Lisi_smoking");}}//mike是好学生,不吸烟class Mike extends College {//复写学习方法void study(){System.out.println("Mike_study");}}class InterfaceDemo{public static void main(String[] args) {Lisi l = new Lisi();l.study();l.smoke();new Mike().study();}}
5.模板方法模式
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减;
获取时间:System.currentTimeMillis();
当代码完成优化后,就可以解决这类问题;这种方式模板方法设计模式;
什么是模板方法呢:
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分;那么这时就将不确定的部分暴露出去,由该类的子类去完成;
package day02;abstract class GetTime{//final关键字不让子类覆盖;public final void getTime(){long start = System.currentTimeMillis();//开始时间runCode();long end = System.currentTimeMillis();//结束时间System.out.print("毫秒:"+(end-start));}public abstract void runCode();//程序代码是不确定的部分,提供抽象方法}class SubTime extends GetTime {//重写抽象方法public void runCode(){for(int i=0;i<10000;i++){System.out.println(i);}}}public class TemplateDemo{public static void main(String[] args){SubTime gt = new SubTime();gt.getTime();}}
- (7)面向对象继承&抽象类&接口
- 面向对象_继承、抽象类、接口
- 面向对象、继承、接口、抽象类
- 面向对象---继承、抽象、接口
- 面向对象--继承、接口、抽象
- java面向对象—抽象类、接口与多继承
- java面向对象—抽象类、接口与多继承
- java面向对象—抽象类、接口与多继承
- java面向对象—抽象类、接口与多继承
- 黑马程序员_day07 面向对象(继承,抽象类,接口)
- 第七天-面向对象(继承,抽象类,接口)
- 黑马程序员---Java基础---面向对象:继承、抽象类、接口
- Java基础--面向对象(继承、抽象类、接口)
- java面向对象浅析--抽象类、接口与多继承
- 方法,面向对象,构造方法,继承,多态,抽象类,接口
- 面向对象(继承-抽象-接口)
- 面向对象(继承-抽象-接口)
- day09_面向对象(继承+抽象+接口)
- 使用DBUS (1): 使用 DBU low-level API
- Java HaspMap高效计数器
- nyij168房间安排(贪心)
- 简述Java内存泄露
- 计算两个文件的相对路径
- 面向对象、继承、接口、抽象类
- 2014NOIP总结
- 007Java对象和类
- 返回按钮和捕获返回键
- 总结经常使用可以提高工作效率的工具集
- 韩语学习网站整理
- LeetCode: Length of Last Word
- Zookeeper实战之使用Zookeeper API
- 精通pl/sql编程