Java知识复习(面向对象)

复习第二天
以下内容参考了《Java编程思想 第四版》 《疯狂Java 第二版》

1.类和对象

定义类

  • Java类名必须是由一个或多个有意义的单词连缀而成,每个单词首字母大写,其他字母全部小写,单词与单词之间不要使用任何分隔符。
  • 类的组成部分:构造器,属性,方法,初始化代码块,内部类(包括接口,枚举)等等。类里各成员定义的顺序没有影响。
  • 创建对象的根本途径是构造器,通过new关键字来调用某个类的构造器即可创建这个类的实例。

this关键字

  • this关键字总是指向调用该方法的对象。
  • this():可以调用构造方法,必须位于构造方法的第一行。
2.方法
  • 方法不能独立定义,方法只能在类体里定义。
  • 从逻辑意义上看,方法要么属于该类本身,要么属于该类的一个对象。
  • 永远不能独立执行方法,执行方法必须使用类或对象作为调用者。

递归方法

  • 一个方法体内调用他自身,被称为方法递归 。
  • 方法递归相当于隐式循环,他会重复执行某段代码,但是无需循环控制。

已知有一个数列:f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),求 f(10).

/**
 * 递归方法
 * @author lw
 *  */
public class Test03 {

    public static void main(String[] args) {
        System.out.println(fn(10));
    }

    public static int fn(int n) {
        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 4;
        } else {
            return 2 * fn(n - 1) + fn(n - 2);
        }
    }
}

方法重载

  • 方法名相同;
  • 参数列表不同(参数个数不同或者参数类型不同);
  • 重载与返回值没有关系,与修饰符没有关系;
  • 重载发生在同一个类中(继承中也有重载);
/**
 * 方法重载
 * 
 * @author lw
 *
 */
public class Test04 {
    public void method(int i, int b) {
        System.out.println(i + b);
    }

    public double method(double a, int b) {
        return a + b;
    }

    private void method(int a) {
        System.out.println(a);
    }
}

构造器

  • 作用:用于创建实例时执行初始化。
  • 构造器名字与类名一样。
  • 如果写的类里面没有构造器,编译器会自动创建一个默认的构造器。
  • 构造器可以重载。
  • 构造器中可以用this关键字调用另一个构造器。

static关键字

  • static方法就是没有this的方法;
  • 在static方法的内部不能调用非静态方法,反过来可以。
  • 无论创建多少个对象,静态数据都只占用一份存储区域。
3.面向对象
  • 面向对象三大特征:封装、继承、多态。

封装

  • 将对象的属性和实现细节隐藏起来,不允许外部直接访问。
  • 暴露方法,让方法来控制对这些属性进行安全的访问和操作。
  • 类是对属性和方法的封装,方法是对代码的封装。

访问修饰符

  • public 接口访问权限
    • 声明自己对每个人都是可用的。
  • default 包访问权限
    • 同一个包中可以访问
  • private 无法访问
    • 除了包含该成员的类之外,其他任何类都无法访问这个成员。
  • protected 继承访问权限
    • 继承关系可访问
.同一个类中同一个包中子类同一个项目
privateok
defaultokok
protectedokokok
publicokokokok

继承

  • 继承用extends关键字来实现,实现继承的类被称为子类。
  • 使用继承可以减少代码量,扩展方便。
  • 一个类只能有一个直接父类,但可以有多个子类。
  • 所有类都是Object类的子类。

class A {

}

class B extends A {

}

class C extends A {

}

class D extends C {

}

子类不能继承父类的成员

  • private修饰的
  • 父类使用默认修饰权限,字类和父类不同包。
  • 构造方法不能被继承。

重写父类的方法

  • 方法名相同
  • 方法的访问修饰符不能严与父类
  • 返回值类型要和父类相匹配
  • 方法的参数列表要和父类相同(不同则是方法重载)
  • 子类不能抛出比父类多的异常

class A {
    public void method(int i) {
        System.out.println(i);
    }
}

class B extends A {
    // 方法重写
    @Override
    public void method(int i) {
        System.out.println(i);
    }

    // 方法重载
    public void method(int i, double b) {
        System.out.println(i + b);
    }
}

super关键字

  • 在子类中调用父类的被覆盖的实例方法,用super关键字。
  • 当调用子类构造器来初始化子类对象时,父类构造器总是在子类构造器之前执行

/**
 * output : A 无参数构造器 
 *          B 一个参数构造器 a= 10
 *          B 两个参数构造器 a=10str...aaa 
 *          C 无参数构造器
 * 
 * @author lw
 *
 */
public class Test06 {
    public static void main(String[] args) {
        new C();
    }
}

class A {
    public A() {
        System.out.println("A 无参数构造器");
    }
}

class B extends A {
    public B(int a) {
        System.out.println("B  一个参数构造器    a= " + a);
    }

    public B(int a, String str) {
        this(a);
        System.out.println("B  两个参数构造器   a=" + a + "str..." + str);
    }
}

class C extends B {
    public C() {
        super(10, "aaa");
        System.out.println("C  无参数构造器");
    }
}

多态

  • 多态是一项让程序员“”将改变的事物与未变的事物分开“”的重要技术
/**
 * output : 父类方法 
 *          子类方法
 * 
 * @author lw
 *
 */
public class Test07 {

    public static void main(String[] args) {
        Parent p1 = new Parent();
        Parent p2 = new Child();
        p1.method();
        p2.method();
    }
}

class Parent {
    public void method() {
        System.out.println("父类方法");
    }
}

class Child extends Parent {
    @Override
    public void method() {
        System.out.println("子类方法");
    }
}
  • 相同类型的变量,调用同一个方法时呈现不同的行为特征,这就是多态。
  • 如何产生多态:
    • 继承关系下
    • 要有方法重写
    • 父类引用指向子类对象
  • 构造器不存在多态性
  • 如果某个方法是静态的,它的行为不存在多态:

public class TestStatic {
    public static void main(String[] args) {
        Parent p = new Child();
        p.method();// output: 父类静态方法
        p.test();// output:子类普通方法
    }
}

class Parent {
    public static void method() {
        System.out.println("父类静态方法");
    }

    public void test() {
        System.out.println("父类普通方法");
    }
}

class Child extends Parent {
    public static void method() {
        System.out.println("子类静态方法");
    }

    @Override
    public void test() {
        System.out.println("子类普通方法");
    }
}

instanceof关键字

  • 前一个操作数通常是一个引用类型变量,后一个通常是一个类或者接口。
        Object str="aa";
        System.out.println(str instanceof Object);
4.初始化
package com.lwcode.ui;

public class Test05 {
    public static void main(String[] args) {
        /*
         *  Aa 的静态初始化快
            Bb 的静态初始化块
            Cc 的静态初始化块
            Aa 的普通初始化块
            Aa 的无参数构造器
            Bb 的普通初始化块
            Bb 的无参数构造器
            Bb 的有参数构造器
            Cc 的普通初始化块
            Cc 的无参数构造器
         */
        new Cc();
        /*
         *  Aa 的普通初始化块
            Aa 的无参数构造器
            Bb 的普通初始化块
            Bb 的无参数构造器
            Bb 的有参数构造器
            Cc 的普通初始化块
            Cc 的无参数构造器
         */
        new Cc();
    }
}

class Aa {
    static {
        System.out.println("Aa 的静态初始化快");
    }
    {
        System.out.println("Aa 的普通初始化块");
    }

    public Aa() {
        System.out.println("Aa 的无参数构造器");
    }
}

class Bb extends Aa {
    static {
        System.out.println("Bb 的静态初始化块");
    }
    {
        System.out.println("Bb 的普通初始化块");
    }

    public Bb() {
        System.out.println("Bb 的无参数构造器");
    }

    public Bb(int a) {
        // 调用自己无参数构造器
        this();
        System.out.println("Bb 的有参数构造器");
    }
}

class Cc extends Bb {
    static {
        System.out.println("Cc 的静态初始化块");
    }
    {
        System.out.println("Cc 的普通初始化块");
    }

    public Cc() {
        // 调用父类有参构造器
        super(1);
        System.out.println("Cc 的无参数构造器");
    }
}
  • 初始化的顺序
  • 静态初始化块–>普通初始化块–>构造器
  • 静态初始化块只执行一次
5.==和equals方法
  • ==:如果两个操作数都是基本类型,且都是数值类型,只要两个变量的值相等,就返回true;(==判断的是数值大小)
    • 如果两个都是引用类型,它们必须指向同一个对象时,==才会返回true;(==判断的是地址是否一致)
  • equals方法:可以自己重写equals方法来定义相同的标准。Object类默认提供的equals方法比较的是对象的地址。
6.final关键字

final修饰属性

  • final修饰的变量为常量,必须赋初值,这个值不能被改变。
  • 一般为了常量使用的便利性,会用static修饰
  • final修饰的是基本数据类型,则不可以改变基本数据类型的值
  • final修饰的是引用类型,则不可以改变引用类型的地址
  • 常量的命名规则:所有字母大写,单词之间用下划线分隔

final修饰方法

  • 把方法锁定,防止任何继承类修改它的定义
  • 确保在继承中使方法行为保持不变,并且不会被覆盖

final修饰类

  • final修饰的类不能被继承,比如String类,Class类,StringBuffer等
7.abstract关键字
  • 抽象类必须用abstract修饰符修饰,抽象方法也必须用abstract修饰符修饰,抽象方法没有方法体
  • 抽象类不能被实例化,不能用new关键字来调用抽象类的构造器创建抽象类的实例。(抽象类里不包含抽象方法也不能创建实例)
  • 抽象类组成:属性,方法,构造器,初始化块,内部类,枚举。构造器不能用于创建实例,主要用于被子类调用。
  • 含有抽象方法的类只能被定义成抽象类。
  • 子类继承抽象类,则必须重写这个类的所有抽象方法,否则这个子类也必须是抽象类。
8.interface关键字

使用接口的好处

  • 接口可以避免Java继承的单根性,一个接口可以继承多个接口
  • 接口更加容易实现多态
  • 接口更加容易搭建框架

接口的组成

  • 接口中只能存放常量和抽象方法
  • 常量默认采用public static final 修饰
  • 方法默认采用public abstract 修饰

使用接口

  • 接口不能创建实例,但接口可以用于声明引用类型变量。
  • 很多软件架构设计理论都倡导“面向接口”编程。
9.单例设置模式

public class PersonTest {
    public static void main(String[] args) {
        Person p1 = Person.getPerson();
        Person p2 = Person.getPerson();
        //输出为true  表明创建的是同一个对象
        System.out.println(p1 == p2);//output : true
    }
}

class Person {
    // 该变量用来存储之前创建的实例
    private static Person person;

    // 构造器采用private修饰,隐藏起来
    private Person() {

    }

    /*
     * 该静态方法用来返回Person实例 加入控制条件保证只产生一个Person实例
     * 
     */
    public static Person getPerson() {
        /*
         * person为null,表明之前还没有创建Person对象
         * person不为null,表明之前已经创建了Person对象,则不再创建新的Person对象
         */
        if (person == null) {
            person = new Person();
        }
        return person;
    }
}
10.代理模式

/**
 * 抽象主题
 * 
 * @author lw
 *
 */
public interface Subject {
    void method();
}
/**
 * 真实类
 * 
 * @author lw
 *
 */
public class Player implements Subject {

    @Override
    public void method() {
        System.out.println("真实类方法");
    }

}

/**
 * 代理类
 * 
 * @author lw
 *
 */
public class Proxy implements Subject {

    private Subject subject;

    public Proxy(Subject subject) {
        this.subject = subject;
    }

    private void method1() {
        System.out.println("代理类自己的方法");
    }

    @Override
    public void method() {
        // TODO Auto-generated method stub
        subject.method();
        method1();
    }

}

/**
 * 测试类
 * 
 * @author lw
 *
 */
public class Test {
    public static void main(String[] args) {
        Player player = new Player();
        Proxy proxy = new Proxy(player);
        proxy.method();
    }
}
11.工厂模式

public class Factories {
    public static void main(String[] args) {
        serviceConsumer(new Implementation1Factory());
        serviceConsumer(new Implementation2Factory());
    }

    public static void serviceConsumer(ServiceFactory serviceFactory) {
        Service service = serviceFactory.getService();
        service.method1();
        service.method2();
    }
}

interface Service {
    void method1();

    void method2();
}

interface ServiceFactory {
    // 返回Service对象
    Service getService();
}

class Implementation1 implements Service {

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

    @Override
    public void method2() {
        System.out.println("Implementation1 method2");
    }

}

class Implementation1Factory implements ServiceFactory {

    @Override
    public Service getService() {
        return new Implementation1();
    }

}

class Implementation2 implements Service {

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

    @Override
    public void method2() {
        System.out.println("Implementation2 method2");
    }

}

class Implementation2Factory implements ServiceFactory {

    @Override
    public Service getService() {
        return new Implementation2();
    }

}
12.内部类

创建内部类

  • 创建内部类的方式就是把类的定义置于外围类的里面。

public class Test01 {

    public static void main(String[] args) {
        System.out.println(Person.I);
    }

    class Person {
        static final int I = 5;
    }
}

使用.this与.new

  • 生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this;

public class Test01 {

    public static void main(String[] args) {
        Test01 test=new Test01();
        Test01.Person person= test.new Person();
    }

    class Person{

    }
}

匿名内部类


public class Test01 {

    public static void main(String[] args) {
        new Thread() {

            @Override
            public void run() {
                super.run();
            }

        }.start();
    }

}
  • 内部类最吸引人的原因:
    • 每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值