1、面向对象都有哪些特性以及你对这些特性的理解
1、封装:封装就是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
2、继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。
继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
3、多态:多态就是用同样的对象引用调用同样的方法但是做了不同的事情,多态性分为编译时的多态性和运行时的多态性,方法重载(overload)实现的是编译时的多态,而方法重写(override)实现的是运行时的多态性,运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1. 方法重写(子类继承父类并重写父类中已有的方法);2. 对象造型(用父类引用子类对象,这样的话同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
4、抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
面向对象分析的步骤:
类和对象:类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体
类用于描述多个对象的共同特征,它是对象的模板。
对象用于描述现实中的个体,它是类的实例。
2、全局变量和局部变量
全局变量存储在堆内存的对象中,所以有默认的初始化值,随着对象的出现而出现在堆中,随着对象的消失而从堆中消失
局部变量存储在栈内存的方法中,因此无默认的初始化值,随着方法的运行而出现在栈中,随着方法的弹栈而消失
全局变量也叫成员变量,是指在类中定义的变量;它在整个类中都有效,又可分为类变量和实例变量。类变量又叫静态变量,用static修饰,它可以直接用类名调用,也可以用对象调用 ,而且所有对象的同一个类变量都是共享同一块内存空间的。实例变量不用static修饰,它只能通过对象调用,而且所有对象的同一个实例变量是共享不同的内存空间的。
全局变量
“0”值
boolean false
char ‘\0’
double 0.0
所有的【类对象】或者【引用数据类型】都是 null
生存周期
随着对象的创建而创建,随着对象的销毁而销毁
局部变量
作用域:局部变量的作用域是在【大括号】以内
生存期:局部变量的生存期也是在【大括号】以内
生存周期:随着方法的弹栈而消失
3、this关键字
作用:this用来调用成员变量。
构造方法和set方法中大量使用
this调用构造方法时必须放第一行
当在方法中出现了局部变量和成员变量同名的时候,那么在方法中怎么区别局部变量和成员变量呢?
可以在成员变量名前面加上this.来区别成员变量和局部变量
this是在方法中使用的,哪个对象调用了该方法,那么,this就代表调用该方法的对象引用
this什么时候存在的?当创建对象的时候,this存在的
this的作用:用来区别同名的成员变量与局部变量(this.成员变量)
super关键字
只要是构造方法默认第一行都是super()
Java体系在设计时定义了一个所有对象的父类Object,自定义类super调用的就是该类
super
使用和this作比较
子类创建对象时,会自动调用父类的构造方法
[建议]存在继承关系下, 父类中最好提供一个无参的构造方法供子类使用
4、封装
封装表现:
1、方法就是一个最基本封装体。
2、类其实也是一个封装体。
好处
1、隐藏了实现细节,还要对外提供可以访问的方式,便于调用者的使用。
2、提高了代码的复用性
3、提高了安全性
5、继承的好处:
1、提高了代码的复用性,提高软件开发效率。
2、让类与类之间产生了关系,提供了多态的前提。
在Java中,如果想实现多继承,可以将这个类的父类去继承另外的父类
当子父类中出现了同名成员变量时,在子类中若要访问父类中的成员变量,必须使用关键字super来完成,若要访问父类中的成员变量,必须使用关键字this来完成。
当在程序中通过对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。
方法重写(覆盖)的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
可以在子类中定义父类的同名方法showNum,然后在子类中的方法中调用super.showNum();,接着编写新的方法。
重写注意事项:
1、子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
2、写法上稍微注意:必须一模一样:方法的返回值类型 方法名 参数列表都要一样。
继承
关键字: extends(包含关系)
子类重写权限:子类必须大于父类权限
优点
简化代码
提高开发效率
游戏开发中使用特别多
特点
父类的构造方法,不能被子类继承
子类可使用父类【非私有化】成员变量和方法
创建子类对象的时候,会首先自动调用父类的构造方法
派生类:子类新增了其他功能
重写
子父类同名、同参数、返回值
【注解】@Override 开启严格的重写检查
6、多态:
Java中多态的代码体现在一个子类对象既可以给这个子类引用变量赋值,又可以给这个子类的父类变量赋值。
那么一个Student对象既可以赋值给一个Student类型的引用,也可以赋值给一个Person类型的引用。
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
在使用多态后的父类在引用变量调用方法时,会调用子类重写后的方法。
多态成员变量
当子父类中出现同名的成员变量时,多态调用该变量时:
编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。
运行时期:也是调用引用型变量所属的类中的成员变量。
简单记:编译和运行都参考等号的左边。编译运行看左边。
多态成员方法
编译时期:参考引用变量所属的类,如果没有类中没有调用的方法,编译失败。
运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员方法。
简而言之:编译看左边,运行看右边。
子类有的调子类,没有的调父类。
多态-转型
多态的转型分为向上转型与向下转型两种:
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型 Person p = new Student();
向下转型:当有父类对象赋值给一个子类引用时,便是向上转型 Student stu = (Student) p;
匿名对象
new 类名().调用的方法()
匿名对象在没有指定其引用变量时,只能使用一次。
多态
含义:张三既是学生也是人,即出现两种形态。
格式:父类 变量名 = new 子类();
父类的引用指向子类的对象
多态成员变量:编译运行看左边。
多态成员方法:编译看左边,运行看右边。
多态的使用注意事项:【背下】
除了非静态方法调子类,其他的都调父类
7、抽象类
产生:某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法
分析事物时,发现了共性内容,就出现向上抽取,可以只抽取出方法声明,那么此方法即为抽象方法
抽象类的特点:
1、抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
2、抽象类不可以直接创建对象,原因:调用抽象方法没有意义。
3、只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。
4、抽象类中可以有抽象方法,也可以没有抽象方法
之所以继承抽象类,更多的是在思想,是面对共性类型操作会更简单。
抽象类的细节问题:
1、抽象类一定是个父类?
是的,因为不断抽取而来的。
2、抽象类中是否可以不定义抽象方法?
是可以的,那这个抽象类的存在到底有什么意义呢?
不让该类创建对象,方法可以直接让子类去使用
3、抽象关键字abstract不可以和哪些关键字共存?
1、private:私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
2、final,暂时不关注,后面学
3、static,暂时不关注,后面学
抽象类
注意事项
被abstract修饰的方法是不能有方法体的
继承该类的子类必须重写这个方法
抽象类不可以直接创建对象
默认修饰
成员变量
public static final
成员方法
abstract
抽象类一定是个父类
8、接口:
在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。
接口最重要的体现:解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。
怎么解决多继承的弊端呢?
弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。
其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
为什么多实现能解决了呢?
因为接口中的功能都没有方法体,由子类来明确。
接口的好处:
1、扩展了功能。
2、降低了耦合性,即设备与设备之间实现了解耦。
接口和抽象类的区别:
相同点:
都只能被其他类实现或继承;
都不能直接实例化对象;
都包含抽象方法,其子类都必须覆写这些抽象方法;
区别:
抽象类中可以有非抽象的方法,接口只能包含抽象方法;
只能单继承抽象类,但是可以多实现接口;
抽象类的继承体系是一种 is…a关系
接口的继承体系是一种 like…a关系
二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
接口中的每个成员变量都默认使用public static final修饰。
所有接口中的成员变量已是静态常量,由于接口没有构造方法,所以必须显示赋值。可以直接用接口名访问。Inter.COUNT
接口
成员变量默认public static
成员方法默认abstract
作用:拓展当前工具的功能
接口是功能的集合,编译后仍然会产生.class文件。
9、构造方法
作用:初始化数据
每次调用构造方法都会自动调用构造代码块
例如:小孩子出生就得哭,可将哭的方法放入代码块中
构造方法没有返回值类型。也不需要写返回值。因为它是为构建对象的,对象创建完,方法就执行结束。
构造方法和一般方法区别:
构造方法在对象创建时就执行了,而且只执行一次。
一般方法是在对象创建后,需要使用时才被对象调用,并可以被多次调用。
构造方法的调用:通过this关键字来调用this(参数列表);
10、static关键字
修饰成员变量,实现数据共享
在eclipse中显示为斜体
存储位置
【静态成员变量】不在【堆区】对象内存中,而在静态数据区
静态的不可以调用非static
生命周期
static成员变量会【早于】类对象的创建而创建,而且【晚于】类对象的销毁而销毁
成员变量是在堆区,随对象的创建而创建(销毁)
调用方式
类名.成员变量
静态方法
【静态成员方法】和对象"无关"
在静态方法中不能使用this关键字
【静态成员方法】里面如何使用【非静态成员变量】?
new对象来调用
什么时候使用static修饰成员方法?
static关键字
我们能不能不创建对象,就可以调用方法呢?
可以的,我们可以通过static关键字来实现。
特点:
1、被static修饰的成员变量属于类,不属于这个类的某个对象。–变量共享
2、被static修饰的成员可以并且建议通过类名直接访问。
注意事项:
1、静态内容是优先于对象存在,只能访问静态,不能使用this/super。静态修饰的内容存于静态区。
2、同一个类中,静态成员只能访问静态成员
3、main方法为静态方法仅仅为程序执行入口,它不属于任何一个对象,可以定义在任意类中。
11、Arrays类
sort()排序
toString()可以代替遍历数组,直接打印数组
binarySearch(arr, 23);二分法查找
找到返回下标
找不到返回-(arr.length+1)
12、final关键字
有些类中的部分方法功能是固定的,不想被继承,不想让子类重写
final可以用来修饰类(不能被继承),成员变量(不能修改),成员方法(不能被重写)及引用类型变量(地址值不变)。
有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写。可是当子类继承了这些特殊类之后,就可以对其中的方法进行重写,那怎么解决呢?
要解决上述的这些问题,需要使用到一个关键字final
1、final修饰类不可以被继承,但是可以继承其他类
2、final修饰的方法不可以被覆盖,但父类中没有被final修饰方法,子类覆盖后可以加final
3、final修饰的变量称为常量,这些变量只能赋值一次
4、引用类型的变量值为对象地址值,地址值不能更改,但是地址内的对象属性值可以修改。
final Person p = new Person();
Person p2 = new Person();
p = p2; //final修饰的变量p,所记录的地址值不能改变
p.name = “小明”;//可以更改p对象中name属性值
5、修饰成员变量,需要在创建对象前赋值,否则报错。
final int n;
public Demo(){
//可以在创建对象时所调用的构造方法中,为变量n赋值
n = 2016;
}
final
成员和局部变量值不变
类不能被继承
方法不能别重写
instanceof关键字
boolean b = 对象 instanceof 数据类型;
13、内部类
成员内部类(类成员位置)
new 外部类名().new 内部类名();
局部内部类(方法体内的类)
代码块
局部代码块:定义在方法或语句中
构造代码块:定义在类中成员位置的代码块
特点:
优先于构造方法执行,构造代码块用于执行所有对象均需要的初始化动作
每创建一个对象均会执行一次构造代码块。
静态代码块:定义在成员位置,使用static修饰的代码块。
特点:
它优先于主方法执行、优先于构造代码块执行,当以任意形式第一次使用到该类时执行。
该类不管创建多少对象,静态代码块只执行一次。
可用于给静态变量赋值,用来给类进行初始化。
包名书写格式
公司网址反写,包名采用全部小写字母,多层包之间用”.”连接
匿名对象:指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。
new Person().eat();
什么时候使用:在描述事物时,若一个事物内部还包含其他可能包含的事物,比如在描述汽车时,汽车中还包含这发动机,这时发动机就可以使用内部类来描述。
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
匿名内部类:匿名内部类是创建某个类型子类对象的快捷方式。
格式:
new 父类或接口(){
//进行方法重写
};
//已经存在的父类:
public abstract class Person{
public abstract void eat();
}
//定义并创建该父类的子类对象,并用多态的方式赋值给父类引用变量
Person p = new Student(){
public void eat() {
System.out.println(“我吃了”);
}
};
//调用eat方法
p.eat();
import 包名.类名;
14、instanceof关键字
boolean flag = new Student() instanceof Student;
15、public、protected、default、private
不同包中无关类、不同包中子类、同一包中子类与无关类、同一类中
归纳一下:在日常开发过程中,编写的类、方法、成员变量的访问
要想仅能在本类中访问使用private修饰;
要想本包中的类都可以访问不加修饰符即可;
要想本包中的类与其他包中的子类可以访问使用protected修饰
要想所有包中的所有类都可以访问使用public修饰。
注意:如果类用public修饰,则类名必须与文件名相同。一个文件中只能有一个public修饰的类。
修饰符
public所有包中的所有类都可以访问
protected本包中的类与其他包中的子类可以访问
default本包中的类都可以访问
private仅能在本类中访问
private修饰的成员变量和成员方法,类外不能进行访问,肿么办?
setter 方法(利用构造方法赋值)
getter 方法(类对象获取值直接打印)
数据还是没有符合生活逻辑,怎么办?
要对setter方法进行限制,让代码符合语法逻辑和生活逻辑,比如说age有范围限制,要通过类对象.setNum()方法进行传值时要在setter方法中加if限制,要在构造方法中进行传值时要在 getter方法中加if限制。
类封装:属性私有化,并且提供setter和getter方法
面向对象、面向接口、面向方法编程的区别?
1、面向过程编程 Procedure Oriented Programming(POP)
分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用。
主要概念:函数、步骤
2、面向对象编程 Object Oriented Programming(OOP)
一堆对象,通过封装、继承、多态等更加有效的组织程序。
3、面向接口编程 Interface Oriented Programming(IOP基于OOP)
一堆接口,通过接口规约对象的属性和方法,是面向对象一部分,只不过面向接口的好处是耦合性低。
4、面向切面编程 Aspect Oriented Programming(AOP)
就是大名鼎鼎的AOP。其实有点像struts里的拦截器。
主要概念:切面、连接点、处理逻辑、切点、引进、目标类、代理类、插入
举例:假如在一个应用系统中,有一个共享的数据必须被并发同时访问,首先,将这个数据封装在数据对象中,
同时,将有多个访问类,专门用于在同一时刻访问这同一个数据对象。
为了完成上述并发访问同一资源,需要引入锁Lock的概念,也就是说,某个时刻,当有一个访问类访问这个数据对象时,这个数据对象必须上锁Locked,用完后就立即解锁unLocked,再供其它访问类访问。 这种加锁与解锁的操作可以使用拦截器来实现。而拦截器本身就是面向方面编程的一个具体应用。
5、面向实现编程 Realize Oriented Programming(ROP基于OOP)
当我们要控制某个类的对象,那么我们会直接在当前程序(自身类)中,实例化该类,然后通过该类调用相应的方法。这是一种最基本的面向对象编程模式。
主要概念:高耦合,不支持多态