Java知识点复习与总结(二)—— 面向对象

Java luoluolzb 浏览1938次

Java 修饰符

访问控制修饰符

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

  1. default (默认值)
    在同一包内可见,不使用任何修饰符。使用对象有:类、接口、变量、方法。
  2. private
    在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
  3. public
    对所有类可见。使用对象:类、接口、变量、方法
  4. protected
    对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
修饰符 当前类 同一包内 子孙类(同一包) 子孙类(不同包) 其他包
public Y Y Y Y Y
protected Y Y Y Y/N N
default Y Y Y N N
private Y N N N N

非访问修饰符

为了实现一些其他的功能,Java 也提供了许多非访问修饰符。

static 修饰符,用来修饰类方法和类变量。

final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

abstract 修饰符,用来创建抽象类和抽象方法。

synchronizedvolatile 修饰符,主要用于线程的编程。

包(package)

Java包这种机制是为了防止命名冲突,类似C++的命名空间。

包使用package声明,一般写在文件第一行,命名方式一般使用反写的域名。例如:

package cn.luoluolzb.www;

public class Test {
    public static void main(String[] args) {
        //some code
    }
}

包的作用

  1. 把功能相似或相关的类或接口组织在同一个包中,方便类的组织和管理。
  2. 包也采用如同目录层次的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。
  3. 限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

导入包

使用import导入一个包中的对象,其语法格式为:

import package1[.package2].(classname|*);

其中*可以导入一个包中所有的东西。

类和对象

使用class关键字定义类,类由方法和属性组成,一般会把属性隐藏(private),只提供对外必要的接口(封装)。

java程序由类组成,一个文件中只能有一个public类,所以一般只在一个文件定义一个类,并且文件名=pubic类名.java

在类中可以使用this关键字访问类方法和变量。

构造方法

构造方法是一种特殊的方法,提供对象的初始化工作,只在对象实例化时被调用一次。

一个类如果没有任何定义构造方法,系统会自动添加一个无参的空方法体的构造方法。但是如果定义了构造方法,系统不会自动生成无参构造方法。

构造方法定义时不能有返回值,方法名要和类名称一致,其他和普通方法定义方法一样。

一个类可以重载定义多个构造方法,在实例化时会根据参数选择合适的构造方法。

例子:

public class Test {
    public Test() {
        System.out.println("Test Constructor1");
    }

    public Test(String s) {
        System.out.println("Test Constructor2");
    }

    public static void main(String[] args) {
        Test t1 = new Test();
        Test t2 = new Test("");
    }
}

输出:

Test Constructor1
Test Constructor2

析构方法

Java中有析构方法,但我们一般用不到它,因为Java有自动内存回收机制,无需手动来释放,在Java中对象销毁前会调用void finalize()方法。

实例化类

类实例化后就是对象,才能使用对象中非静态的成员。实例化一个类的方法:

ClassName class = new ClassName(Arguments);

new 后面的方法实际上是类的构造方法,从这里能看出来为什么构造方法定义时没有返回值了,因为会它会自动返回对象的引用。

静态变量和静态方法

Java使用static声明静态成员,表示该成员是该类所有对象共有的,因此可以通过类名直接访问静态成员(当然也可以用对象访问,但推荐使用类名)。

静态变量在类被定义时初始化,程序结束时被回收。

静态成员可以在非静态方法和静态方法中使用。但是静态方法中只能使用静态成员。

初始化块和静态初始化块

Java中除了可以在构造方法中初始化变量外,也可以在初始化块中进行相关初始化工作。静态初始化块在程序执行后调用。

定义方法:

public class Test {
    String name;
    static int count;

    //初始化块
    {
        name = "luoluolzb";
    }

    //静态初始化块
    static {
        count = 0;
    }

    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.name);
        System.out.println(Test.count);
    }
}

重载(Overload)

重载即在一个类中可以使用重载定义多个相同方法,但需要方法的 返回值类型 或者 参数列表 不同。

重载实现了体现了面对对象编程的多态性。

重载例子:

public class Test {
    public static int max(int a, int b) {
        return a > b ? a : b;
    }

    public static double max(double a, double b) {
        return a > b ? a : b;
    }

    public static void main(String[] args) {
        System.out.println(max(3, 4));
        System.out.println(max(3.14, 4.2));
    }
}

类的继承

使用extends进行类的继承,Java中只能单继承,即只能有一个直接父类,但可以多层继承。

子类可以继承父类的方法和属性,无需重复编写代码,使用final声明类可以防止类被继承。

重写(Override)

重写是指子类对父类的方法进行重新编写, 返回值和形参列表都不能改变。即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要改变父类的方法。

在子类中仍然可以通过super关键字访问父类中被重写的方法和属性。

继承的例子:

class A{
    public String name;

    public A(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void say() {
        System.out.println("A:I am " + name);
    }
}

class B extends A{
    public B(String name) {
        super(name);  //调用父类构造方法
    }

    public void say() {  //重写say方法
        System.out.println("B:I am " + name);  //name继承的
    }
}

public class Test {
    public static void main(String[] args) {
        A a = new A("classA");
        a.say();

        B b = new B("classB");
        b.say();
        System.out.println(b.getName());  //getName继承的
    }
}

抽象类

抽象类使用 abstract class 定义,抽象类是一种特殊的类,它不能被实例化,但可以被子类继承。

抽象类中可以定义普通的方法和属性,最重要的是可以通过 abstract 声明抽象方法,继承了抽象类的普通子类必须要重写抽象方法,否则子类需声明为抽象类。

abstract class A{
    public int a;  //普通熟悉
    public void fun() {}  //普通方法
    public abstract void say();  //抽象方法
}

class B extends A{
    @Override
    public void say() {  //必须重写抽象方法
        System.out.println("I am B.");
    }
}

public class Test {
    public static void main(String[] args) {
        //A a = new A();  //语法错误,抽象类不能被实例化
        B b = new B();
        b.say();
    }
}

接口

接口只是一个规范,可以保证继承该接口的子类都遵循这些规范。

接口在Java中是一种抽象类型,不能被实例化,它是抽象方法的集合(只能声明方法),使用interface定义。

类继承接口:一个类使用implements继承一个或多个接口,必须实现每个接口里面的声明的方法。

接口继承接口:一个接口使用extends能继承另一个接口或多个接口,子接口继承父接口的方法。

/* 文件名 : Animal.java */
interface Animal {
   public void eat();
   public void travel();
}
/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{

   public void eat(){
      System.out.println("Mammal eats");
   }

   public void travel(){
      System.out.println("Mammal travels");
   } 

   public int noOfLegs(){
      return 0;
   }

   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

抽象类和接口的区别

抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。

接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。

共同点如下:

  1. 都是上层的抽象层。
  2. 都不能被实例化
  3. 都能包含抽象的方法,这些抽象的方法用于描述类具备的功能,但是不比提供具体的实现。

区别如下:

  1. 在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象类的优势;接口中只能有抽象的方法。
  2. 一个类只能继承一个直接父类,这个父类可以是具体的类也可是抽象类;但是一个类可以实现多个接口

什么时候使用抽象类和接口

  1. 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
  2. 如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个3. 类,但可以实现多个接口。因此你就可以使用接口来解决它。
    如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。

参考资料:

  1. http://www.importnew.com/12399.html
  2. https://www.zhihu.com/question/20149818#answer-52437385

本文标签: Java

版权声明:本文为作者原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://luoluolzb.cn/articles/49/java-zhi-shi-dian-fu-xi-yu-zong-jie-er-mian-xiang-dui-xiang
您需要登录后才发布评论。 点此登录
用户评论 (0条)

暂无评论,赶紧发表一下你的看法吧。