总览
java类主要由成员和方法组成,面向对象四大特征 抽象、封装、继承、多态,定义类的过程就是抽象和封装的过程,接口和抽象类 则是对实体类进行更高层次的抽象,接口和抽象类都不能被实例化,但是可以定义引用变量指向实例对象。
——《java编程思想》
面向对象的思想
- 当你拿到一个问题时,你分析这个问题不再是第一步先做什么,第二步再做什么,这是面向过程的思维
- 你应该分析这个问题里面有哪些类和对象,这是第一点,然后再分析这些类和对象应该具有哪些属性和方法,这是第二点,最后分析类和类之间具体有什么关系,这是第三点
封装
- 把数据和方法包装到类中,以及具体实现的隐藏,通常共同被称为封装
- 访问权限的控制被称为具体实现的隐藏,private防止属性被其他类直接修改,如需修改,使用get/set方法
- 把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中
继承
- 继承是所有oop语言和java语言不可缺少的部分
- 创建一个类,总是在继承,除非明确继承了其他类,否则就是隐式的继承Ojbect
- 为了继承,一般数据成员设为private,方法设为public
- 先执行父类构造方法,再执行子类构造方法
public class Father {
protected static String fatherName = "fatherName";
static {
System.out.println("father static");
}
public Father(String name){
System.out.println("father constructor");
}
}
public class Sun extends Father {
static {
System.out.println("Sun static");
}
public Sun() {
super("");
getStr2();
System.out.println("sun construct");
}
static String getStr(){
return "";
}
String getStr2(){
return "";
}
public static void main(String[] args) {
new Sun();
}
}
输出:
father static
Sun static
father constructor
sun construct
如果父类没有无参构造方法,那么子类的构造方法中,需要先显式的调用父类的有参构造 super("");,先执行父类构造函数,在执行子类构造函数
抽象
- 抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处
- 抽象类体现的是 is-a的关系,接口则是can-do的关系
- 接口是顶级的类,编译之后还是.class结尾
- 比如什么是瓶子,有个口,能倒水,能盛水,什么形状的都有;给瓶子下定义的过程,就是抽象,
- 使用抽象可以避免考虑一些与目标无关的细节,比如一个简单的薪酬系统,只需要关心姓名,工号,薪水等,要善于划分问题的边界,当前系统需要什么,就只考虑什么
class Person{
String name;
String jobNumber;
BigDecimal salary;
}
多态
- 动态绑定 ,java中除了static和final(包括private方法)方法之外,其他方法都是动态绑定,即运行时判断对象的类型]
- 向上转型 , 向上转型不要强制转型。向上转型后父类的引用所指向的属性是父类的属性,如果子类重写了父类的方法,那么父类引用指向的或者调用的方法是子类的方法,这个就叫动态绑定
Father father = new Son();
- 向下转型,使用 instanceof 来避免ClassCastException, 用处是把类的对象传递给其他方法,节约代码,传递的参数是父类对象,但是实际调用时传递子类对象 ,也提现了抽象编程
Son son =(Son)father;
- 实现多态的3个条件 继承 重写 向上转型
- 在Java中有两种形式可以实现多态。继承和接口
内部类
- 静态内部类
- 成员内部类,一般private class Inner{}
- 方法内部类
- 匿名内部类,(new Thread()).start()
public class InnerTest {
//成员内部类
private class Inner{ }
//静态内部类
static class StaticClass{ }
public static void main(String[] args) {
//匿名内部类
(new Thread(new Runnable() {
@Override
public void run() { } })).start();
(new Thread()).start();
//方法内部类,不允许拥有修饰符
class Method1Class{ }
}
}
this 关键字
总结:
- super()和this()均需放在构造方法内第一行
- this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数
- this()和super()都指的是对象,均不可以和static同时出现
看一段代码
public class Leaf {
int i = 0;
public Leaf(int i) {
this.i = i;
}
Leaf increament() {
i++;
return this;
}
void print() {
System.out.println("i = " + i);
}
public static void main(String[] args) {
Leaf leaf = new Leaf(100);
leaf.increament().increament().print();
}
}
Leaf leaf = new Leaf(100);
程序执行到这里的时候,栈空间里面有一个变量leaf,它指向了我们new出来的在堆空间里面的Leaf对象,构造方法里面有一个形参i,所以在栈空间里面给构造方法分配有一小块内存
构造方法执行完之后,为这个构造方法分配的内存消失,所以栈里面的i所标记的那一小块内存会消失。因此第一句话执行完之后,内存中的布局如下图所示:
接下来又是栈里面的那个新的this调用print()方法,使用this来调用,那就相当于是Leaf对象来调用,Leaf对象自己调用print()方法将自己的i属性的值打印出来,所以打印出来的结果应该是102
this一般出现在方法里面,当这个方法还没有调用的时候,this指的是谁并不知道。但是实际当中,你如果new了一个对象出来,那么this指的就是当前这个对象。对哪个对象调用方法,this指的就是调用方法的这个对象(你对哪个对象调用这个方法,this指的就是谁)。如果再new一个对象,这个对象他也有自己的this,他自己的this就当然指的是他自己了。
super关键字
- 子类构造过程中,自动执行父类构造方法,默认调用无参构造方法
-当我们new一个子类对象的时候,这个子类对象里面会包含有一个父类对象
面向对象和面向过程的利弊
- 面向过程 性能好,可维护性、可复用性差
- 面向对象 性能弱,因为类加载 消耗资源较大,但是由于具有封装、继承、多态等特性,容易设计出低耦合的系统,代码更加灵活