Java基础-面向对象

一.

面向过程单位:函数;面向对象单位:类 

JAVA类及类的成员:属性,方法,构造器;代码块,内容类

面向对象的特征:封装,继承,多态

关键字使用:this,super,package,import,static,final,interface,abstract等

类和对象:类是对相同事物的抽象,对象是具体(实例)

面对对象设计三步骤

  1. 设计类就是设计类的的成员:属性-field,方法-method
  2. 创建类的对象
  3. 通过类的对象调用其内部的属性和方法

对象在(jvm)内存中的分配涉及的内存结构(不涉及的有程序计数器,本地方法栈)

栈:对象名,存放对象在内存中的地址

堆:对象实体,包括属性(new 产生的)

方法区:加载类的模板结构

局部变量和属性在内存分配位置不同:属性随着对象的创建,存在堆中;局部变量存在栈中

生命周期属性随对象,局部变量随相应方法栈帧

局部变量不可以用权限修饰符修饰,而属性可以(封装性)

属性都有默认初始化值,而局部变量没有默认初始化值,使用前需要显式赋值

java中方法不区分相互顺序

方法的重载:同一个类中,允许同名方法,但满足参数不同(与形参名,权限修饰符,返回值无关)

相同的方法:方法名相同,形参列表相同

*println的重载:除char[]外形参都是对象,char[]的形参就是char[];

可变形参(int... a):实际调用时实参个数0个-多个;多个形参时可变形参必须声明在列表最后

可以与同类下同方法民构成重载(特例:参数为同类型的数组参数)

方法的值传递机制(Java的传递机制)

方法内声明的局部变量/方法的参数传递

基本数据类型:传递的是值

引用数据类型:传递的是地址

import关键字:显式引入指定包下的类

权限修饰符修饰类或类的内部成员:private,缺省,protected,public;当这些成员被调用时,可体现可见性的大小(体现封装性,满足高内聚低耦合需求)

Java基础-面向对象_第1张图片

main方法用private修饰则不再作为程序的入口 

构造器( 类名() ):搭配new关键字,创建类的对象,在创建对象的同时,给对象相应属性初始化(系统默认提供一个空参的构造器,构造器权限与类相同,构造器也可以重载)

匿名对象(new () xxx),且匿名对象只能调用一次

未用static修饰的属性是实例变量,每一个对象都有单独的属性

类中属性赋值方法:默认初始化,显式初始化,构造器初始化,对象.方法;对象.属性;

Javabean:公用的类,提供空参公共的构造器,有属性且提供get()与set();

UML图:Java基础-面向对象_第2张图片

二.

this关键字

应用场景:set方法的形参与属性名重名,用于表明当前(正在创建-在构造器中)对象的属性

this可以调用的结构:成员变量与方法(未用static修饰的),构造器

this在类中调用其它构造器可以使用this(形参)调用其它构造器,且必须声明在首行,因此一个构造器中最多声明一个其它构造器

快速创建get,set方法-alt+insert

面向对象特征二:继承性

考虑角度:自上而下,自下而上 

好处:减少冗余,利于扩展,多可表示为is-a关系,为多态提供前提,子类获取父类中声明的属性和方法(不继承构造器),但是由于封装性可能不能直接调用一些属性和方法,还可以具有自己特有的部分

Java中的类,没显式表明其父类,则默认父类java.lang.object

java中类支持多层继承(直接父类,间接父类),单继承性(子类只能有一个父类,此局限性可以通过类实现接口解决)

方法的重写:子类对从父类继承而来的方法进行覆盖(子类与父类中同名的属性不会覆盖,用关键字进行区分,this与super)

重写的规则:方法名与形参列表必须保持不变,子类重写的方法的权限修饰符权限不小于父类中的修饰符(子类不能重写父类中private的方法,因为子类不能访问父类的private方法),返回值类型,父类为void或基本数据类型,则子类保持一致;若为引用数据类型,则子类中需一致或为其子类(抛出异常类型也是这个规则)

重载:两同一不同;重写:继承之后,覆盖同名同参的方法

super关键字:在子类中调用被子类重写的父类中的方法,调用父类中同名的属性,亦可以调用父类中的构造器(super(形参列表),只能写在首行,且与this(形参列表)只能存在一个,若都未调用,则默认调用父类空参构造器super())

在通过子类构造器创造对象的时候,一定在调用子类构造器的过程中直接或间接的调用了父类的构造器(一个类中n个构造器,最多n-1个中使用this(),至少一个使用super())

父类子类属性重名,调用方法时涉及该名属性按就近一致原则,即父类方法得到父类中属性,子类方法(或重写的方法)得到子类中属性

面向对象特征三:多态性(子类方法的多态性,方法的重写,决定了抽象类和接口的出现)

前提:继承关系,方法重写

体现:声明父类类型,赋予子类对象(多用于方法传参)

应用:虚拟方法调用(编译时认为是父类方法,执行时是子类重写的方法;编译看左,运行看右,在运行时体现出多态性)因此多态性只适用于方法,不适用于属性(编译与运行都看声明类型)

优劣:减少冗余与方法重载(抽象具体子类,易于扩展,eg:equals());创建的子类对象,加载了子类特有的属性方法,但声明为父类,并不可以直接调用

弊端解决:多态的逆过程-向下转型(转型前用instanceof判断,避免转换异常,格式 a instanceof B,判断对象a是否是类B的实例)

默认的父类(根类)-object类:无属性,一个空参构造器,11个通用方法

重点(2):

  • equals()适用性:任何引用数据类型,使用:自定义的类未重写前,调用的都是object类中的方法,比较的是两个的地址,已重写的类string,file,date和包装类等,重写逻辑:先比地址,再比类型(instanceof),最后比属性(快速重写alt+insert),区分==[使用范围基本与引用数据类型,基本比较值,引用比较地址值]与equals()
  • toString()打印对象所属类和地址值(默认),已重写的类string,file,date和包装类等返回的是实体内容,system.out.println(对象会默认调用tostring)

了解(2)

  • clone():复制创造一个对象
  • finalize():GC回收垃圾时调用该方法-可能导致内部循环引用

三.

static关键字:静态的,用于修饰属性,方法,代码块,内部类

成员变量,用static-静态变量,类变量(有类即有,可以直接被类调用,也可以被对象调用,多个对象共享),不用-实例变量(创建对象才有,每个对象1份,只有对象能调用)

静态方法内可以调用静态属性和静态方法,不可以调用非静态成员(非静态中可调用静态),也不能用this与super,成员前省略的是类名(静态方法不可被重写,不存在多态性,与对象无关)

单例设计模式-某个类只能存在一个对象实例

实现:类的构造器私有化,在类的内部创建当前类的实例(此属性声明为static),通过static的get()得到构建的实例

两种模式:饿汉式-立即加载当前唯一实例(内存中加载较早,使用更快,线程安全的,但占用内存时间较长);懒汉式-延迟加载,使用时才创建实例(节省内存,但线程不安全)

类的成员:代码块与内部类

代码块:用于初始化类或对象信息,只能用static修饰(静态代码块-随着类的加载而执行,类只加载一次,则其只执行一次,初始化类的信息;非静态代码块-随着对象的创建而执行,多次创建对象,多次执行,初始化对象的信息【执行在构造器之前,与显式初始化的次序决定执行顺序】),可以有多个(多个之间的执行顺序按照声明顺序),静态代码块内部只能调用静态结构,不能够调用非静态的

代码块应用:不同构造器内相同的部分可提取到代码块,静态属性的初始化复杂的情况

内部类:定义在类中的类-遵循高内聚,低耦合

应用:thread中的state-表示线程生命周期

分类:成员内部类-静态(new 外部类.内部类)非静态(外部类对象.new 内部类),与类有相同性质,权限修饰符还可以用private和protected;局部内部类-匿名非匿名(匿名类或对象)

内部类可以调用外部类的属性和方法:外部类.this.结构

类的加载:由父及子(构造器一致)

final关键字的使用:修饰类(则不可被继承),方法(不可被重写),变量(只能赋值一次,视作常量,对于成员变量-显式赋值,代码块赋值,构造器赋值;局部变量-赋值后,不可更改)

final与static结合修饰成员变量:全局常量

抽象类与抽象方法(包含抽象方法的类必须是抽象类):abstract修饰类,抽象类不能实例化但包含构造器(因为子类需要调用),抽象类可以没有抽象方法;抽象的方法只有声明没有方法体,其功能已确定只是不知如何具体实现,实现交由子类,子类只有重写所有抽象方法后才可实例化(此时该子类才不是抽象类)

abstract不能修饰属性,构造器,代码块等;abstract不能与私有方法(私有方法不可重写),静态方法,final修饰的方法(不能重写),final修饰的类(不能继承)

接口:本质是规范,关键字interface,体现关系式a能够b,属性必须使用public static final修饰,方法(jdk8前)-抽象方法,abstract public修饰,修饰均可省略,不可以声明构造器,代码块

接口与类是实现关系,类可以实现多个接口(弥补单继承局限性),方法未全部实现则为抽象类

接口与接口是继承关系,可以多继承

接口的多态性,声明接口,指向实现接口的类

创建匿名实现类的对象,用接口名创建对象临时重写抽象方法 new 接口(){重写};

抽象类与接口:共-都可以定义抽象方法,都不能实例化,异-抽象类有构造器,接口无构造器

jdk8接口新特性:静态方法-只能通过接口调用,不能通过实现类调用;默认方法-实现类可以继承且重写,实现类实现多个接口中存在同名同参默认方法,则必须对其重写;类优先原则-子类继承父类且实现了接口,同名同参方法未重写,则调用的是父类中的;在子类中调用接口中的默认方法-接口名.super.方法名

jdk9-接口中可以定义私有方法

涉及的匿名声明方法(内部类):

public class OuterClassTest2 {
    public static void main(String[] args) {

        SubA a = new SubA();
        a.method();

        //举例1:提供接口匿名实现类的对象
        A a1 = new A(){
            public void method(){
                System.out.println("匿名实现类重写的方法method()");
            }
        };

        a1.method();

        //举例2:提供接口匿名实现类的匿名对象
        new A(){
            public void method(){
                System.out.println("匿名实现类重写的方法method()");
            }
        }.method();

        //举例3:
        SubB s1 = new SubB();
        s1.method1();

        //举例4:提供了继承于抽象类的匿名子类的对象
        B b = new B(){
            public void method1(){
                System.out.println("继承于抽象类的子类调用的方法");
            }
        };

        b.method1();
        System.out.println(b.getClass());
        System.out.println(b.getClass().getSuperclass());

        //举例5:
        new B(){
            public void method1(){
                System.out.println("继承于抽象类的子类调用的方法1");
            }
        }.method1();

        //举例6:
        C c = new C();
        c.method2();

        //举例7:提供了一个继承于C的匿名子类的对象
        C c1 = new C(){};
        c1.method2();
        System.out.println(c1.getClass());
        System.out.println(c1.getClass().getSuperclass());


        C c2 = new C(){
            public void method2(){
                System.out.println("SubC");
            }
        };
        c2.method2();

    }
}

interface A{
    public void method();
}

class SubA implements A{

    @Override
    public void method() {
        System.out.println("SubA");
    }
}

abstract class B{

    public abstract void method1();

}

class SubB extends B{

    @Override
    public void method1() {
        System.out.println("SubB");
    }
}


class C{
    public void method2(){
        System.out.println("C");
    }
}

枚举类(enum):类的对象有限且确定,若实例只有一个可以用单例模式实现

定义方式:私有化类的构造器;类内部创建对象,public static final修饰(jdk5前,class定义)

对象省去修饰词,放在类开头,对象间用逗号隔开(jdk5,,enum定义,继承父类Enum)

枚举类实现接口:类中重写方法,每个对象调用方法一致;在创造对象时重写方法,各不相同

常用方法:

  •  String toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法!
  •     (关注)static 枚举类型[] values():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法
  •     (关注)static 枚举类型 valueOf(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。
  •     String name():得到当前枚举常量的名称。建议优先使用toString()。
  •     int ordinal():返回当前枚举常量的次序号,默认从0开始

注解:@注解名

常用注解:@override-重写;@deprecated-过时,可以用;@suppresswarning-抑制编译警告

元注解:对现有的注解进行解释说明的注解。
(1)@Target:用于描述注解的使用范围
可以通过枚举类型ElementType的10个常量对象来指定
TYPE,METHOD,CONSTRUCTOR,PACKAGE.....

(2)@Retention:用于描述注解的生命周期
可以通过枚举类型RetentionPolicy的3个常量对象来指定
SOURCE(源代码)、CLASS(字节码)、RUNTIME(运行时)
唯有RUNTIME阶段才能被反射读取到。

(3)@Documented:表明这个注解应该被 javadoc工具记录。
(4)@Inherited:允许子类继承父类中的注解

Junit单元测试-白盒测试

单元测试方法,需要满足:- 所在的类必须是public的,非抽象的,包含唯一的无参构造器。
- @Test标记的方法本身必须是public,非抽象的,非静态的,void无返回值,()无参数的。

包装类:使基本数据类型具有引用数据类型的相关特征

Java基础-面向对象_第3张图片

基本数据类型与包装类之间转换:前-后:使用包装类的构造器;包装类的valueof();

自动装箱-直接赋值(jdk5新特性);

后-前:包装类的xxxvalue();自动拆箱-直接赋值(jdk5)

string与基本数据类型,包装类的转换:

前-后:调用相应包装类.paresXxx(xxx);

后-前:调用string的静态方法valueof(xxx);+“”连接运算;

参考试题:

//说明:如果赋值的值在[-128,+127]范围内,
//则Integer对象使用的是IntegerCache中数组cache中的元素

public class InterviewTest1 {
	public static void main(String[] args) {
		
		Integer i = new Integer(1);
		Integer j = new Integer(1);
		System.out.println(i == j);//false

		//底层都会调用Integer的valueOf()
		Integer m = 1; //自动的装箱
		Integer n = 1;
		System.out.println(m == n);//true

		Integer x = 128;
		Integer y = 128;
		System.out.println(x == y);//false

	}

}

Java基础-面向对象_第4张图片

面向对象的理解:(核心)-类与对象,三大特征;接口

你可能感兴趣的:(java,开发语言)