首先谈一下面向对象编程(OOP),面向对象编程主要针对业务处理过程的实体及其属性进行抽象封装,以获得更加清晰和高效的逻辑单元划分。主要为了实现编程的重用性,灵活性和扩展性。它的几个特征分别是封装,继承,抽象,多态。OOP重点体现在编程架构,强调的是类之间的层次关系。
继承:在Java中定义一个类时,让该类通过关键字extends继承一个已有的类。这就是类的继承。
被继承的类称为父类或超类,新的类称为子类。
子类继承父类所有的属性和方法,同时也可以添加自己的属性和方法。
继承的好处:使编码更高效,易维护,代码的重用。
继承的规则:Java中只支持单继承,每个类只能有一个父类,不允许有多重继承。
一个父类可以有多个子类。
子类继承父类的所有属性和方法。
子类实例化的过程:子类先实例化父类,然后实例化子类。要先调用父类的构造器,父类的构造器运行完毕,才调用子类的构造器。
super和this关键字:
super()作用是调用父类的构造器,只能出现在子类的构造器中,且必须是第一行,super()中的参数,决定了调用父类哪个构造器,如果子类构造器中没有出现super(),即调用父类的空构造器,如果父类没有空构造器,编译器提示错误。
this()作用:调用本类构造器,只能写在构造器的第一行。
在同一个构造器中super()和this()不能同时出现。
super()指向父类引用,this()指向本类引用。
封装:信息隐藏,隐藏对象的实现细节,不让用户看到。将方法和属性一起包装到一个单元中,单元以类的形式体现。隐藏属性、方法或实现细节的过程称为封装。
访问权限修饰符:用来控制类的成员和类的使用范围,类的成员访问权限修饰符:private、default、protected,public,类的访问权限修饰符:public default
多态:同一实现接口,使用不同的实例而执行不同的操作。
不同的对象对同一行为作出不同响应。
多态存在的三个必要条件,要有继承或实现,要有重写,父类引用指向子类对象。当调用父类中被重写的方法后,运行时创建的哪个子类的对象,就调用该子类中重写的那个方法。在执行期间,判断所引用对象的实际类型,根据其实际类型调用相应的方法。
多态的优点:简化代码,改善代码的组织性和可读性,易于扩展。
方法的覆盖(override):重写,对从父类中继承的方法进行改造,在子类继承父类时发生。
规则:相同的方法名,相同的参数列表,相同的返回值类,子类覆盖方法的权限不小于父类被覆盖方法的权限。
抽象:
抽象方法:只有方法声明,没有实现的方法。
抽象类:抽象方法和非抽象方法的集合。可以全部是抽象方法,全部是非抽象方法。
规则: 抽象类不能被实例化。
其包含的抽象方法必须在子类中被实现,否则该子类只能声明为abstract。
抽象方法不能为static。
在下列情况下,一个类必须被声明为抽象类:
当一个类的一个或多个方法是抽象方法时;
当类是一个抽象类的子类,并且没有实现父类所有的抽象方法,只实现部分;
当一个类实现一个接口,并且不能为全部抽象方法都提供实现时。
接口:
接口的声明:接口中只包含常量和抽象方法,而没有变量和方法的实现。
接口不是一个类,没有构造器,不能被实例化。
接口使用interface关键字定义
接口默认:常量:public static final
抽象方法:public abstract
接口和类的关系:类实现接口。
为了使用一个接口,你要编写实现接口的类。
如果一个类要实现一个接口,那么这个类就必须实现接口中所有抽象方法,否则这个类只能声明为抽象类。
多个无关的类可以实现一个接口,一个类可以实现多个无关的接口。
一个类可以在继承一个父类的同时,实现一个或多个接口。
接口的意义:
接口可以实现多继承:
用接口可以实现混合类型,java中可以通过接口分出主次类型
主类型使用继承,副类型使用接口实现。
接口可以使方法的定义和实现相分离,降低模块间或系统间的耦合性。
接口与抽象类的区别:
接口不能含有任何非抽象方法,而抽象类可以。
类可以实现多个接口,但只能有一个父类。
接口不是类分级结构的一部分,没有联系的类可以实现相同的接口。
final关键字:final可以修饰的元素:
类:不能被继承。
变量:(属性和局部变量):不能被重新赋值在声明时赋值,或在构造器中赋值系统不会对final属性默认的赋初始值。
方法:不能在子类中被覆盖,即不能修改。
内部类:(嵌套类)
内部类就是定义在另一个类内部的类。
内部类对于同一个包中的其他类来说,内部类能够被隐藏起来。
内部类可以访问其外部类中的所有变量和方法。
无需创建外部类的对象,即可从内部类访问外部类的变量和方法。
必须创建内部类的对象,否则无法从外部类访问内部类的变量和方法。
如果内部类中有和外部类同名的变量和方法,则内部类的变量和方法将获得比外部类变量和方法更高的优先级。
不能定义static变量。
普通类的访问权限修饰符:public,default,内部类的访问权限修饰符:public,default,protected,private
类中定义内部类:
public class Outer {<span style="white-space:pre"> </span>//外部类
private int varOuter=100;
class Inner {<span style="white-space:pre"> </span>//内部类
int varInner=200;
public void showOuter() {
System.out.println(varOuter);
}
}
public void showInner() {
Inner i=new Inner();
System.out.println(i.varInner);
}
}
<span style="white-space:pre">Inner in = new Inner() ; </span>//在Outer内访问Inner 创建内部类对象
//Outer外访问Inner
Outer o = new Outer(); //实例化外部类
Outer.Inner oi = o.new Inner(); //实例化内部类
静态内部类:用static标识的内部类为静态内部类。
静态内部类作为外部类的静态成员,不能访问外部类非静态成员。
非静态内部类只能定义非静态成员,而静态内部类可以定义静态成员和非静态成员。
使用Outer.Inner inn=new Outer.Inner()方式实例化静态内部类。
非静态内部类不可以使用上面的方式实例化。
局部内部类:在一个类的方法体中或程序块内定义的内部类。
//类中定义的内部类
class A{
int a;
public void method(){
}
class B{ }
}
//局部内部类
class A{
int a;
public void method( int c ){
int b=0;
class B{ }
}
}
//在方法中定义的内部类只能访问方法中final类型的局部变量
public class Outer2 {
public int a = 1;
private int b = 2;
public void method( final int c) {
int d = 3;
final int e = 2;
class Inner {
private void iMethod( int e) {
//System.out.println(e);
}
}
}
}
匿名 类:匿名类是不能有名称的类,所以没办法引用它们。必须在创建时,作为new语句的一部分来声明它们。其语法如下所示:
new <类或接口> {
<类的主体>
}
Java中的包:是类,接口和子包的集合。
Java中常用的包:java.lang Java语言包,任何程序中,该包都被自动导入。
java.awt 图形用户界面包。
java.awt.event 图形用户界面处理包。
java.swing 跨平台轻量级组件包。
java.sql 数据库访问包。
java.io 输入、输出操作有用的类组成
java.util 提供了许多创建如:lists,calendar,date等所需的类和接口。
java.net 该包提供了许多进行TCP、IP网络编程的类和接口。
通过import导入。
AOP(面向切面编程):是Aspect Oriented Programming的缩写,即面向切面编程,是一种可以通过预编译方式和运行期动态代理实现在不修改源代码情况下,给程序动态同一 添加功能的一种技术。
针对业务处理过程中的切面进行提取,它所面对的是处理过程中某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
实现方法:
方法一:Spring 经典的AOP 实现
1. 实现MethodInceptor 接口,在其invoke() 方法中定义行为(Advice )
2. 使用ProxyFactoryBean 生成代理
<bean id="factoryBean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref=” 目标对象”></property>
<property name="interceptorNames">
<list> 切面列表</list>
</property>
</bean>
方法二:利用Spring 提供的自动代理生成器
自动代理生成器其实是在方法一的基础上再次封装,为我们提供了更强大的功能,同时操作也更方便。
特点:完全基于XML 配置;能够使用AspectJ 的切点表达式。
示例:
1. 配置文件中添加aop 命名空间,完整的根节点定义如下:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
</beans>
2. 添加如下配置:
<aop:config>
<aop:pointcut id="pc"
expression="within( 选择要切的类)"/>
<aop:aspect ref=" 切面">
<aop:before pointcut-ref="pc" method=" 切面中的方法"/>
</aop:aspect>
</aop:config>
除了aop:before 外,还有多种Advice
before 表示 切面在切点之前;
after-returning 表示 切点方法执行完毕成功返回后执行切面方法;
after-throwing 表示 切点方法抛出异常时执行切面方法;
after 表示 无论切点方法是否成功返回,都执行切面方法;
around 表示 切点方法执行期间执行切面方法,也就是自定义执行顺
序。
around 对方法有如下要求:
1, 返回类型Object
2, 参数ProceedingJoinPoint
3,throws Throwable
AspectJ 切点表达式:
within: 匹配类内的所有方法(必须是实现类,不能是接口)
如 :within(first.Singer)
execution: 匹配指定的方法
execution(void perform()) 匹配项目下所有该方法
execution(void first.Singer.perform()) 匹配具体到某个类的该方法
execution(* first.Artist.perform()) 不考虑返回值类型
execution(* first.Artist.perform(..)) 不考虑返回值类型和参数列表
execution(* first.Aritst.perform(*,*)) 参数必须是两个
execution(* first.Artist.perform(..,java.lang.String))
execution(* find*(..)) 所有方法名符合findXxx 的方法
execution(* com.tarena.service.StoreService.*(..)) 该类中所有方法
execution(* com.tarena.service.*.*(..)) 该包中所有类的所有方法
execution(* com.tarena..*.*(..)) 该包及其子包中所有类的所有方法
条件运算符:not and or
within(first.service.StoreService) or execution(* first.dao.*.*(..))
三.切面方法中如何获得切点信息?
around 对方法要求有参数ProceedingJoinPoint ,所以可以很容易的获得切点对象的相关信息。那么after, before 等其他的切面类型对方法没有这样的要求,该怎么获得切点信息呢?
对于这些方法,可以直接为其添加JoinPoint 参数,这样就可以获得
方法对象,参数列表,目标对象,代理对象 的信息。
返回值和异常则可以直接接受,然后在配置中添加属性即可。例如:
方法签名为:public void after(JoinPoint jp, Object res, Exception e)
配置信息为:<aop:after-returning returning="res" …> 则在方法中可以直接使用切点方法返回的对象res ;同样 < aop:after-throwing throwing="e"…> ,在方法中也可以直接接收到异常对象。