1. 面向对象简介
面向对象是一种编程思想
1.1 与面向过程区别
面向过程
遇到一个问题,亲力亲为的一步步解决他(小兵),典型代表语言:c
面向对象
遇到一个问题,找具有解决这个问题的对象,调用这个对象的方法(老板),典型代表java
内存分配情况:
class Demo{
public static void main(String[] args){
Person person = new Person();
person.name = "张三";
person.country = "中国";
Person person2 = new Person();
person.name = "李四";
person.country = "台湾";
person.sleep();
person2.sleep();
}
}
class Person{
String name;
static String country;
public void sleep(){
System.out.println(name+"======"+country);
}
}
图片如下:
1.2. 封装工具类
方法都用static
开头写一个构造方法 private Demo(){}
1.3. 代码块
构造代码块
{
......
}
静态代码块
static{
.......
}
特点
使用一个类时,这个类中的静态代码块会自动执行
只会执行一次,第一次使用该类,就立刻执行
在同一个类中,静态代码块的优先级很高,比构造方法优先,比main方法优先
1.4. 继承
1.4.1 优点
提供了代码的复用性
提高代码的可维护性
1.4.2 缺点
增加了类的耦合性
耦合
类与类的关系
内聚
自己完成某件事情的能力
1.4.3 注意事项
子类不能继承父类的构造方法,可以通过super去访问
不要为了部分功能而去继承,继承是一种关系的提现
子类的构造方法默认会访问父类中的空参构造方法;因为每一个构造方法的第一句默认都是 super();因为子类继承父类就是需要父类中的数据
如果父类有有参构造,没有空参构造;子类中还是会在构造方法中加一条super();父类不会自动产生无参构造,那么就会报错,
在子类手动写一个super(参数);
在子类无参构造写一个this(参数)来调用子类是有参构造
this()和super()不能同时存在
不管是用过父类new子类,还是子类new子类 调用的方法都是子类中重写的
1.4.4 执行过程
class Fu {
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
class Test{
public static void main(String[] args){
Zi zi = new Zi();
zi.show();
}
}
class Fu1 {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu1() {
System.out.println("构造方法Fu");
}
}
class Zi1 extends Fu1 {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi1() {
System.out.println("构造方法Zi");
}
}
class Test1{
public static void main(String[] args){
Zi1 zi1 = new Zi1();
}
}
jvm调用了main方法,main先进栈
遇到new子类
将父类.class和子类.class分别加载进内存
创建对象
当父类.class加载进内存父类的静态代码块会随着父类.class一起加载
子类静态代码块会随着子类.class一起加载进内存
开始走子类的构造方法,因为java中是分层初始化的,先初始化父类,再初始化子类,所以先走父类
父类初始化结束,子类开始初始化
1.5 接口与抽象类
1.5.1 相同点
都不能创建对象
都是作为父类/接口
子类/实现都必须重写方法,然后才能创建对象
1.5.2 不同点
抽象类用关键字abstract接口用关键字interface
抽象类中可以有抽象方法,可以没有抽象方法,也可以部分是抽象方法
接口中只有方法,都必须是抽象的
抽象类可以定义任意成员变量,接口的成员变量必须加上public static final修饰
类和抽象类之间的关系是单继承,类和接口的关系是多实现
思想上的区别
抽象类中必须定义整个继承体系的共性内容
接口中定义整个继承体系同之外的额外的扩展的功能
抽象类为部分方法提供实现,避免了子类重复实现这些方法,提高代码重用性
抽象类为继承体系中的共性内容,接口为继承体系外的扩展功能
1.5.3 二者选用
优先选用接口,尽量少使用抽象类
需要定义子类的行为,又要为子类提供共性功能时才轩选用抽象类
1.5.4 多态
前提
必须有子父类关系(必须有继承)
必须有方法的重写
表现形式
父类类型 变量名 = new 子类类型();
注意事件
成员变量编译和运行都是使用的父类的
成员方法编译时看父类,运行时看子类
缺点
多台只能调用子父类共有的方法,不能调用子类特有的方法
优点
提高了程序的灵活性
父类类型的变量可以接受任何一个子类的对象
编译时看父类,运行时看子类
解决不能调用子类特有方法
向上向下转型
强制转换
instanceof运算符 可以判断是不是某个类型
1.5.5 匿名内部类
作用
快速创建抽象类的子类对象,接口实现类对象
public abstract class AbstractAnimal {
public abstract void eat();
public abstract void speeack();
}
利用内部类快速创建抽象类的子类
public static void absTest(){
Dog dog = new Dog();
dog.eat();
dog.speeack();
new AbstractAnimal(){
@Override
public void eat() {
System.out.println("不好吃");
}
@Override
public void speeack() {
System.out.println("哈哈哈");
}
};
//匿名内部类
new AbstractAnimal(){
@Override
public void eat() {
System.out.println("不好吃");
}
@Override
public void speeack() {
System.out.println("哈哈哈");
}
}.eat();
//利用多态 父类对象接受子类对象
AbstractAnimal absAnimal = new AbstractAnimal() {
@Override
public void eat() {
System.out.println("一般般");
}
@Override
public void speeack() {
System.out.println("对的");
}
};
absAnimal.eat();
absAnimal.speeack();
}
利用内部类快速创建接口的子类
public interface NuNi {
void cook();
void daoShui();
void moMo();
}
public static void infTest(){
new NuNi(){
@Override
public void cook() {
}
@Override
public void daoShui() {
}
@Override
public void moMo() {
}
};
new NuNi(){
@Override
public void cook() {
}
@Override
public void daoShui() {
}
@Override
public void moMo() {
}
}.cook();
NuNi nn = new NuNi() {
@Override
public void cook() {
}
@Override
public void daoShui() {
}
@Override
public void moMo() {
}
};
nn.cook();
nn.daoShui();
nn.moMo();
}
1.5.6 内部接口
public interface InternalInterface {
void showOut();
interface InInterface{
void showIn();
}
}
class InfDemo implements InternalInterface{
@Override
public void showOut() {
}
}
class Inf2Demo implements InternalInterface.InInterface{
@Override
public void showIn() {
}
}
1.5.7 内部类
public class InternalClass {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
class IntClass{
private String age;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
}
class IntClassDemo extends InternalClass{
}
class Int1ClassDemo extends InternalClass.IntClass {
}
1.5.8 static
存在方法区中的静态区,只有一个空间
静态是优先于对象存在的
如何访问static成员
对象名.静态成员;//不建议
类名.静态成员;//建议
1.5.9 finally
final修饰类:不能被继承(没有子类),但是可以是其他类的子类
修饰方法(最终方法,牛逼):子类不能重写
修饰成员变量
这个成员变量在创建对象之前必须初始化
只能赋值一次
修饰局部变量
基本类型
该变量只能赋值一次(常量)
引用类型
改引用类型的变量的地址不能改变
地址指向空间中的内容可以改变