面向过程和面向对象
- 面向过程:Object Oriented Programming
- 强调功能行为,以函数为最小单位,考虑如何做
面向对象:Procedure Oriented Programming
java类及类的成员
- 属性:类中的成员变量
- 方法:(method)类中的成员方法
- 构造器
- 代码块
- 内部类
- 面向对象的三大特征
- 封装性(Encapsulation)
- 继承性(Interitance)
- 多态性(Polymorphism)
- (抽象性)
- 其他关键字
this
super
static
final
abstract
interface
package
import
面对对象的思想概念
- 类(class)和对象(Object)是面对对象的核心概念
- 类是对一个事物的描述,是抽象的、概念上的定义
- 对象是实际存在的该类事物的每个个体,因而也成为了实例(instance)
-
参数
public void show(String ... str);//可变参数
// 这是一个string的数组,允许写入多个string
封装性和隐藏性
封装的作用和意义:
- 保护程序的可复用性和可维护性,减低程序员保持数据与操作内容的负担
- 对象的私有数据和共有数据隔离开来,保护私有数据,避免模块之间存在的干扰
- 减低程序 复杂性、提高可控的目的
- “高内聚,低耦合”
- 高内聚:类的 内部数据操作细节自己完成,不允许外部干扰
- 低耦合:仅对外暴露少量的方法用于使用
- 隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用。
- 提高系统的可延展性、可维护性
- 封装性的体现,需要权限修饰符来配合
private
:类内部缺省/default
:类内部、同包protected
:类内部、同包、不同包public
:类内部、同包、不同包、工程内
修饰符
构造器的特征
- 它具有与类系统的名称
- 他不声明不返回值类型。(与声明的void不同)
- 不能被static、final、synchronized、abstract、native修饰
- 构造器的作用
- 创建对象时给对象进行初始化
说明
JavaBean是一种java语言写成的可重用组件
- javaBean是指符合 如下标准的java类
- 类是公共的
- 有一个无参的公共的构造器
- 有属性、且有对应的get、set方法
package
- 声明类或接口所属的包,声明在源文件的首行
import
主要代码:public class sub extends parent
子类(sub)继承了父类(parent)中声明的结构、属性、方法
- java继承规定:
- 一个类允许被多个子类继承
- java中类是单继承性,一个类只允许继承一个父类
- 子类是相对的概念(多层继承)
- 子类直接继承叫做直接父类,间接继承的叫做间接父类
- 子类继承父类后,获得了直接和间接获取所有父类声明的结构属方法
```java
public class person{
String name;
String sex;
int age;
public void eat(){
System.out.println(name + “在吃饭”);
}
public void sleep()[
System.out.println(name + “在睡觉”);
} } public class Student extends person{
}
<a name="P6Vrs"></a>
# 方法的重写(overwrite)
- 方法名、形参、返回值与父类方法一致
- 返回值可以是A类型 或者 是A类型的子类
- object(父类)=>String(子类)
- double(父类)≠>int(子类)---int和double是并列关系
- 权限不能小于父类方法
- 子类不能重写父类声明的 private 权限方法
- 表现为多态性
<a name="jmMQ4"></a>
# 方法的重载(override)
- 当包名、方法名、构造器相同时,会出现方法重载
- 方法参数不同、类型不同。
- 不表现为多态性
```java
public void show(int a);
public void show(double a);
public void show();
public void show(int a, int b);
关键字super
- 可以调用父类的属性、方法、构造器
this
和super
的区别就是- this优先调用当前类中的属性、方法、构造器
- super调用父类中的属性、方法、构造器
- 子类和 父类同名时,容易冲突
this();
表示当前构造器super();
表示调用父类构造器
多态性Polymorphism
- 子类对象可以用父类进行声明
- 当用父类声明时,只能调用父类所声明的东西,子类特有的无法调用
instanceof
在强制类型转换、向下转型时,避免出现ClassCastException
的异常。
在向下转型时先进行instanceof判断,一旦返回true就进行向下转型。
父亲不能变成儿子,儿子可以变成父亲number instanceof int
name instanceof String
uncleObj instanceof manObj
JDK5.0新特性:自动装箱、自动拆箱
```java // 自动装箱:基本数据类型->包装类 int num1 = 10; Integer in1 = num1;// 手动装箱:基本数据类型->包装类
int num1 = 10;
Integer in1 = new Integer(num1);
boolean b1 = true;
Boolean B1 = new Boolean(b1);
// 手动拆箱:包装类->基本数据类型
int num2 = IntegerValue(in1);
boolean b2 = BooleanValue(B1);
boolean b1 = true; Boolean B1 = b1; // 自动拆箱:包装类->基本数据类型 int num2 = in1; boolean b2 = B1;
<a name="nOqCl"></a>
# 基本数据类型与 String类型的互相转换
```java
// 基本数据类型、包装类->String类型
int num1 = 10;
String str1 = num1 + "";// 连接运算
String str2 = String.valueOf(num1);// 调用String.valueOf()
// String->int
String str1 = "123";
int num1 = Integer.ParseInt(str1);
// NumberFourmatException
// String -> Boolean
String str2 = "true";
boolean b1 = Boolean.parseBoolean(str2);
单列设计模式
概念:由于单例模式只生成一个实例,减少了系统性能开销。
当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,
则可通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
应用场景:
- 网站的计数器
- 应用程序的日志应用
- 数据库连接池
- 读取配置文件的类
- Application是单例应用
- Windows的Task Manager(任务管理器)就是一个单例模式
- windows的Recycle Bin(回收站)也是单例应用
饿汉式(提前造好)
public class test{
public static void main(String[] args){
Bank b1 = Bank.getInstance();
Bank b2 = Bank.getInstance();
System.out.println(b1 == b2); // true
}
}
class Bank{
// 1. 私有化类的构造器
private Bank(){}
// 2. 内部创建类的对象,此对象也要是静态类
private static Bank() instance = new Bank();
// 3. 提供公共的静态方法,返回类的对象
public static Bank getInstance(){
return instance;
}
}
懒汉式 (何时用何时造,有就不造)
public class test{
public static void main(String[] args){
Order o1 = Order.getinstance();
Order o2 = Order.getinstance();
system.out.println(o1 == o2); // true
}
}
class Order{
// 1. 私有化类的结构
private Order(){}
// 2. 声明当前类对象,没有初始值,必须是static
public static Order instance = null;
// 3. 声明public、static的返回当前类对象的方法
public static Order getInstance(){
if (instance == null){
return new Order();
}
return instance;
}
}
饿汉式和懒汉式的区别
- 加载区别
- 饿汉式提前加载,随时能加载
- 懒汉式不提前加载,需要用时才加载
- 内存区别
- 饿汉式提前加载,占用内存
- 懒汉式用时才加载,不占内存
作用区别
main()作为程序的入口
- main()也是一个普通的静态方法
- main()可以作为我们与控制台交互的方式
代码块
静态代码块和非静态代码块的区别
- 相同
- 内部可以有输出
- 按照先后顺序执行
- 静态代码块
- 随着类的加载而执行,只执行一次
- 初始化类的信息
- 优先执行静态代码块
- 静态代码块只能调用静态属性和静态方法,不能调用非静态结构
- 非静态代码块
- 随着对象的创建而执行,每创建一次执行一次
- 可以在创建对象时,进行初始化
- 非静态代码块能调用非静态结构和静态结构
- 运行顺序“静态模块”>“非静态模块”和“构造器”
- 有父类优先运行父类
```java
public class code {
public static void main(String[] args) {
} }class people{ static {System.out.println(“people-静态代码块:1”);} {System.out.println(“people-非静态代码块:3”);} public people() {System.out.println(“people-无参构造器:4”);} public people(String name) {new student("小明");
} }this();
System.out.println(name+"people-带参构造器:5");
class student extends people{ static{System.out.println(“student-静态代码块:2”);} {System.out.println(“student-非静态代码块:6”);} public student() {System.out.println(“student-无参构造器:无”);} public student(String name) { // this(); // 不允许同时出现super和this,所以student无参构造器无法执行 super(name); System.out.println(“student-带参构造器:7”); } } / people-静态代码块:1 student-静态代码块:2 people-非静态代码块:3 people-无参构造器:4 people-带参构造器:5 student-非静态代码块:6 student-带参构造器:7 /
```java
{
// 代码块
}
static{
// 代码块
}
class类 属性赋值顺序
- 默认初始化
- 显式初始化 / 代码块赋值 (位置顺序)
- 构造器中初始化
创建多选后通过“对象.属性” 或者 “对象.方法”的方式,进行赋值
final:最终的
final修饰类
public final class name{}
/final class name{}
- 此类不能被其他类所继承,不允许有子类
- 例如:String、System、StringBuffer
- final修饰方法
public final void show(){}
- 此方法不能被重写
- final修饰变量
final int age = 10
- 变量此时就是一个常量,只允许一次赋值操作
- final修饰属性允许:显式初始化、代码块中初始化、构造器中初始化
- final修饰局部变量
- 抽象类
- abstract创造对象后无法实例化
- 通常都会给子类进行实例化
- 抽象方法
- 抽象方法只能在抽象类中
public abstract void eat();
- 抽象方法只有方法声明,没有方法体
- 声明抽象方法时,子类需要进行重写,否者子类也要是个抽象类
- 使用注意
- abstract不能修饰属性、构造器等结构,不能修饰私有方法、静态方法、final的类和方法
抽象类匿名对象
```java class drive{ public static void main(String[] args){ method(new Person(){
}); } public static void method(Person p){ p.eat(); p.breath(); } }public void eat(){
System.out.println("吃好喝好");
}
public void breath(){
System.out.println("呼吸空气");
}
- abstract不能修饰属性、构造器等结构,不能修饰私有方法、静态方法、final的类和方法
abstract class Person{ abstract public void eat(); abstract public void breath(); }
<a name="dsmlv"></a>
# 接口
1. 版本问题
1. JDK7及以前:里面只能定义全局常量和抽象方法
1. 全局常量:`public static final` (可以省略)
1. 抽象方法:`public abstact` (可以省略)
2. JDK8:还可以定义静态方法和默认方法(可省略public)
1. 静态方法:`public static void method(){}`
1. 接口定义的静态方法,只能在接口中调用
1. `CompareA.method1()`
2. 默认方法:`public default void method(){}`
1. 通过实现类的对象,可以调用接口中的默认方法
1. `new SubClass().method2()`
1. 实现类重写了默认方法,则会调用重写方法
1. 如果子类(实现类)继承父类方法时,先父类后接口
1. 在实现类有多个接口,并且多个接口有同名同参的方法时报错,需要重写
1. 实现类中调用指定接口`CompareA.method1();`
2. 使用方法
1. 接口创建`interface Flyable{}`
1. 接口使用`class Plane implements Flyable{}`
1. 对象单继承、多接口`class Plane extends Obj implements Flyable, aa{}`
1. 接口多继承`interface aa extends bb, cc{}`
3. 接口的使用体现多态性
<a name="kaTtS"></a>
# 代理模式
1. 代理模式是java开发中使用较多的一种设计模式。
1. 代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
2. 代理场景
1. 安全代理:屏蔽对真实角色的直接访问。
1. 远程代理:通过代理类处理远程调用(RMI)。
1. 延迟代理:先加载轻量级的代理对象,真正需要加载真实对象。
3. 分类
1. 静态代理:静态定义代理类
1. 动态代理:动态生成代理类
<a name="GyaQB"></a>
# 工厂模式
1. 代理模式和面对对象设计原则都是为了使得开发项目更加容易扩展和维护,解决方法就是“分工”
1. 实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离起来,达到提升灵活性的目的。
2. 工厂3个原则(共6个)
1. OCP(开闭原则,open-closed principle)
1. 代码不能随着需求变化而变化,可以通过新增代码解决新需求。
1. 修改原代码会造成原代码无法正常运行,使维护工作剧增。
2. DIP(依赖倒转原则,dependence inversion principle)
1. 要针对接口编译,不要针对实现编译。
3. LOD(迪米特法则,law of demeter)
1. 尽量少暴露出没有必要的代码
3. 工厂模式的分类
1. 简单工厂模式(Simple Factory):用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
1. 工厂方法模式(Factory Method):用来生产同一等级结构中的固定产品。(支持增加任意产品)
1. 抽象工厂模式(Abstract Factory):用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
<a name="kQHn0"></a>
# 内部类
内部类分为成员内部类(静态、非静态)、局部内部类(方法内、代码块内、构造器内)
- 可以调用外部类的结构
- 可以被static修饰
- 可以被4种不同的权限修饰
关注问题
- 如何实例化成员内部类的对象?
- 静态内部类:`Person.Heart h = new Person.Heart();`
- 非静态内部类:`Person p = new Person();Person.Heart h = new p.new Heart();`
- 如何在成员内部类中区分调用外部类的结构?
- `Person.this.name;`
- 开发中局部内部类的使用?
局部内部类中调用局部变量时,局部变量要求声明为`final`,JDK8及后自动声明
```java
// 局部内部类的使用
public Comparable getComparable(){
// 方法一
class MyComparable implements Comparable{
// 内部类代码
}
return new MyComparable();
// 方法二:返回匿名类
return new Comparable(){
// 内部类代码
};
}
class Person{
class Heart{ /*成员内部类*/ }
static class Craw{ /*静态成员内部类*/ }
public void method(){
class AA{
/*局部内部类*/
public void test(){
person.this.eat();
}
}
}
public void eat(){print("吃")}
}
抽象类和接口的区别
- 相同点:不能实例化、都可以被继承
- 不同点:
- 抽象类:有构造器、单继承
- 接口:没有构造器、多继承