面向对象

  • 面向对象就是一种常见的思想,符合人们的思考习惯;
  • 面向对象的出现,将复杂的问题简单化;
  • 面向对象的出现,让曾经在过程中的执行者,变成了对象中的指挥者。

成员变量和局部变量的区别
1,成员变量存在类中,整个类都可以访问
局部变量定义在函数,语句,局部代码中,只在所属的区域有效。

2,成员变量存在于堆内存的对象中。
局部变量存在于栈内存的方法中。

3,成员变量随着变量的创建而存在,随着对象的消失而消失;
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。

4,成员变量都有默认初始化值,
局部变量没有默认初始化值。

this关键字
1、this调用本类中的属性,也就是类中的成员变量;
2、this调用本类中的其他方法;
3、this调用本类中的其他构造方法,调用时要放在构造方法的首行

静态关键字static
静态变量:static的主要目的就是创建独立于具体对象的域变量与方法。
随着类被加载时,static所修饰的成员都被加载出来了。
static变量并不是所在类的某个具体对象所有,而是该类的所有对象所共有的,静态变量既能被对象调用,也能直接拿类来调用;除此之外,静态变量不能引用非静态方法,原因正如前面描述静态加载时机中说的那样,加载静态的时候,非静态的变量、方法等还不存在。但是,非静态方法或类却能正常引用静态变量或方法。因为非静态总是在静态之后出现的。

静态方法:和静态变量一样,属于类所有,在类加载的同时执行,不属于某个具体的对象,所有对象均能调用
它们仅能调用其他的static方法。
它们只能访问static数据。
它们不能以任何方式引用thissuper
(静态方法一般用于工具类中,可以直接拿类名调用工具方法进行使用。)

静态类:一般一个普通类是不允许被声明为static的,但是,在内部类中可以将其声明为static的,这个时候,外部类可以直接调用内部类,因为static的内部类是在加载外部类的同时加载的,所以也就是说,并不要实例化外部类就能直接调用静态内部类。

public class BaseStatic {
  static {
        System.out.println("Load base static");
    }

    public BaseStatic(){
        System.out.println("BaseStatic constructor");
    }
    
    static class BaseInnerClass{
        static{
            System.out.println("Base inner class static");
        }
        
        public BaseInnerClass(){
            System.out.println("BaseInnerClass constructor");
        }
    }

}


public class StaticLoadOrderTest{

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new BaseStatic.BaseInnerClass();
    }

}

设计模式:对问题行之有效的解决方式,强调的是解决问题的思想。
1、单例设计模式:
解决的问题:保证一个类在内存中的对象唯一性。
1、不允许其他程序用new创建该类对象。
2、在该类创建一个本类实例。
3、对外提供一个方法让其他程序可以获取该对象。

步骤:
1、创建一个私有静态的实例对象;
2、私有化构造函数,防止其在外部创建新的对象;
3、对外开放一个静态的函数返回该实例,可以直接使用类名进行调用(static关键字)。

//饿汉式,可以防止多线程并发时的问题
class Single
{
    private static Single s = new Single();//封装/防止外部函数进行直接调用。
    private Single(){}
    public static Single getInstance()
    {
        return s;
    }
}
//懒汉式,会延迟创建新的对象,调用方法时才会创建新对象
class Single2
{
    private static Single2 s = null;
    private Single2(){}
    public static Single2 getInstance()
    {
        if(s == null)
            s = new Single2();
        return s;
    }
}

面向对象的三大特性
封装
良好的封装能减少耦合型;
类内部的结构可以自由修改;
可以对成员进行更精确的控制;
隐藏信息和实现的细节。
继承
类于类之间存在所属关系的时候,就会定义继承。
java 不直接支持多继承,因为多个父类中有相同成员时,会产生调用的不确定性。

  • 成员变量:和父类同名时,需要用super区分。
    super和this`使用方法类似

this 是对本类对象的引用
super 代表一个父类空间。

  • 成员函数:当子父类中出现同名时,会出现覆盖现象。
    函数的两个特性(覆盖overload和重载override“在同一个类中”)。
    覆盖的使用场景:当一个类进行子类的扩展时,子类需要保留父类的功能声明,但要定义子类特有功能时,需要使用覆盖。。
    子类中:在实例化的过程中都会访问父类中空参数的构造函数。

  • 抽象类特点abstract
    1、方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。抽象方法必须定义在抽象类中,该类必须也被abstract修饰。
    2、抽象类不能被实例化,因为抽象方法没有意义。
    3、抽象类必须由其子类将所有抽象方法进行覆盖后,才能进行实例化。否则,该子类还是一个抽象类。

1、抽象类中有构造函数没?
有,用于给子类对象进行初始化。
2、抽象类可以不定义抽象方法吗?
可以,但是很少见,目的就是不让该类创建对象。AWT适配器就是这种类。
3、抽象类不可以和哪些关键字一起使用:
private不行,不能覆盖
static不行,
final不行。
4、抽象类和一般类的异同点:
相同点:都是用来描述事物的,内部都定义了成员。
不同点:
a、一般类有足够的信息描述事物,抽象类描述事物的信息不足;
b、一般类不能定义抽象方法,抽象类可以定义一般方法;
c、一般类可以实例化,抽象类不能被实例化。
5、抽象类一定是一个父类吗?
是的。

  • 当一个类中都是抽象方法时,可以定义接口,interface
    全局常量:public static final
    抽象方法:public abstract
    接口和类之间是实现的关系。。implements
    接口不能直接实例化。
    可以多实现。。
    接口是对外暴露的规则
    接口是程序的功能扩展
    接口的出现降低程序的耦合性
    接口可以用来多实现。
    接口和接口之间可以有继承关系

接口和抽象类的异同:
相同点:都是不断向上抽取而来的。
不同点:1、抽象类需要被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
2、抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。
接口中只能定义抽象方法,必须有子类去实现。
3、抽象类的继承,是is a 的关系,在定义该体系的基本共性内容。
接口的实现是like a 的关系,在定义体系额外功能。

  • final:继承的弊端:打破了封装性。
    1、final是一个修饰符,可以修饰类、方法、变量;
    2、final修饰的类不可以被继承;
    3、final修饰的方法不可以被覆盖;
    4、final修饰的变量是一个常量,不可以被再次赋值。

多态
父类或接口的应用指向了子类的对象。。

多态的好处:提高了代码的扩展性和重复性;
多态的弊端:前期的定义内容不能使用后期的功能;
多态的前提:
1、必须要有关系继承,实现。
2、必须要有覆盖。

  • instanceof 用于判断具体类型,用于向下转型健壮性的判断

  • 多态时,成员的特点:
    成员变量:编译运行都参考左边。
    成员函数:编译看左边,运行看右边
    静态函数:编译运行都看左边,静态时方法储存在静态区中,不需要对象,不直接使用类名调用就可以。

  • 内部类的访问特点:
    1、内部类可以直接访问外部类的成员,
    2、外部类需要创建对象来访问内部类的成员。
    当分析事物中,发现事物内部还有事物,而且这个事物还访问描述事物内部的内容,这时候就需要内部类。

内部类在局部位置上只能访问final修饰的变量
内部类必须实现接口或者继承父类。

  • 匿名内部类:new 父类or接口(){ 子类内容}是一种简写格式
    通常的使用场景之一是:当函数参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类进行传递。

一个对象在实例化的过程
Person p = new Person();
1、jvm会读取指定路径下的Person.class文件,并加载进内存,并会加载Person的父类(如果有直接的父类的情况下),
2、在堆内存中开辟空间,分配地址;
3、并在对象空间中,对对象中的属性进行默认初始化;
4、调用对应的构造函数进行初始化;
5、在构造函数中,第一行会先调用父类中的构造函数进行初始化。
6、父类初始化完毕后,在风中子类的属性进行显示初始化;
7、再进行子类构造函数的特定初始化;
8、初始化完毕后,将地址值赋值给引用变量。


面向对象_第1张图片
面向对象内存图解

你可能感兴趣的:(面向对象)