Java面向对象中的关键字


今天继续Java系列,上篇写到了java面向对象的三大特征,今天看下面向对象中的关键字。

package

package称为包,用于指明该文件中定义的类、接口等结构所在的包。

如何使用

格式如下:

package 顶层包名.子包名 ;

示例:pack1\pack2\PackageTest.java

package pack1.pack2; //指定类PackageTest属于包pack1.pack2

public class PackageTest{
	public void display(){
		System.out.println("helllo");
	}
}

注:

  • 一个源文件只能有一个声明包的package语句
  • package语句作为java源文件的第一条语句出现,若缺省该语句,则指定为无名包
  • 包名属于标识符,满足标识符命名的规则和规范(全部小写)、见名知意,包通常使用所在公司域名的倒置,另外取包名时不要使用java.xxx
  • 包对应于文件系统的目录,package语句中用.来指明包的层次,每.一次就表示一层文件目录
  • 同一个包下可以声明多个结构(类、接口),但是不能定义同名的结构(类、接口),不同的包下可以定义同名的结构(类、接口)

应用示例

包可以包含类和子包,划分项目层次,便于管理。包可以帮助管理大型软件系统,将功能相近的类划分到同一个包中,比如MVC的设计模式。包有效的解决了类命名冲突的问题。包还可以控制访问权限。

示例:MVC设计模式。
MVC是一种软件构建模式,目的是为了降低程序开发中代码业务的耦合度。

MVC设计模式将整个程序分为三个层次:视图模型层(viewer)、控制器层(controller)与数据模型层(model)。这种将程序输入输出、数据处理、以及数据的展示分离开来的设计模式使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程序的耦合性。

视图层viewer:显示数据,为用户提供使用界面,与用户直接进行交互。

  • 相关工具类:view.utils
  • 自定义view:view.ui

控制层controller:解析用户请求,处理业务逻辑,给予用户响应。

  • 应用界面相关:controller.activity
  • 存放fragment:controller.fragment
  • 显示列表的适配器:controller.adapter
  • 服务相关的:controller.service
  • 抽取的基类:controller.base

模型层model:主要承载数据、处理数据。

  • 数据对象封装:model.bean/domain
  • 数据库操作类:model.dao
  • 数据库:model.db

JDK中主要包的介绍:

  • java.lang:包含一些java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能
  • java.net:包含执行与网络相关的操作的类和接口
  • java.io:包含能提供多种输入输出功能的类
  • java.util:包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数
  • java.text:包含了一些java格式化相关的类
  • java.sql:包含了java进行JDBC数据库编程的相关类/接口
  • java.awt:包含了构成抽象窗口工具集的多个类,这些类被用来构建和管理应用程序的图形用户界面

import

为了使用定义在其它包中的java类,需要用import语句来显式引入指定包下所需要的类,相当于import语句告诉编译器到哪里去寻找这个类。

如何使用

格式如下:

import 包名.类名

注:

  • import语句声明在包的声明和类的声明之间
  • 如果需要导入多个类或接口,那么就并列多个import语句即可
  • 如果使用a.*导入结构,表示可以导入a包下的所有结构
  • 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句
  • 如果已经导入java.a包下的类,那么如果需要使用a包的子包下的类的话,仍需导入
  • 如果在代码中使用不同包下的同名类,那么需要使用类的全类名的方式指明调用的是哪个类
  • import static组合的使用:调用指定类或接口下的静态的属性或方法

应用示例

示例:

import pack1.pack2.Test; //import pack1.pack2.* 表示引入pack1.pack2包中的所有结构

public class PackTest{
	public static void main(String args[]){
		Test t = new Test(); //Test类在pack1.pack2包中定义
		t.display();
	}
}

this

在java中this关键字不算难理解,它的作用和其词义很接近。this在方法(准确点应该是实例方法或非static的方法)内部使用,表示调用该方法的对象。this也可以在构造器内部使用,表示该构造器正在初始化的对象。

如何使用

this可以调用的结构有:成员变量、方法和构造器。

在实例方法或构造器中,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的可读性,不过通常都习惯省略this。但是当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量。即可以用this来区分成员变量和局部变量。

this可以作为一个类中构造器相互调用的特殊格式,this()调用本类的无参构造器,this(实参列表)调用本类的有参构造器。

应用示例

实例方法或构造器中使用当前对象成员的示例:

public class Rectangle {
    int length;
    int width;
    public int area() {
        return this.length * this.width;
    }
    public int perimeter(){
        return 2 * (this.length + this.width);
    }
    public void print(char sign) {
        for (int i = 1; i <= this.width; i++) {
            for (int j = 1; j <= this.length; j++) {
                System.out.print(sign);
            }
            System.out.println();
        }
    }
    public String getInfo(){
        return "长:" + this.length + ",宽:" + this.width +",面积:" + this.area() +",周长:" + this.perimeter();
    }
}

:使用this访问属性和方法时,如果在本类中未找到,会从父类中查找。

同一个类中构造器相互调用示例:

public class Student {
    private String name;
    private int age;
    //无参构造
    public Student() {
    //this("",18); //调用本类有参构造器
    }
    //有参构造
    public Student(String name) {
        this(); //调用本类无参构造器
        this.name = name;
    }
    //有参构造
    public Student(String name,int age){
        this(name); //调用本类中有一个String参数的构造器
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getInfo(){
        return "姓名:" + name +",年龄:" + age;
    }
}

:不能出现递归调用,比如调用自身构造器,如果一个类中声明了n个构造器,则最多有n-1个构造器中使用了this(形参列表)。this()和this(实参列表)只能声明在构造器首行,在类的一个构造器中,最多只能声明一个this(参数列表)。

super

super用于Java的类中,实现调用父类中的指定操作。

如何使用

super可用于访问父类中定义的属性、可用于调用父类中定义的成员方法、可用于在子类构造器中调用父类的构造器。

  1. 子类中调用父类被重写的方法。
  • 如果子类没有重写父类的方法,只要权限修饰符允许,在子类中完全可以直接调用父类的方法
  • 如果子类重写了父类的方法,在子类中需要通过super.才能调用父类被重写的方法,否则默认调用的子类重写的方法
  1. 子类中调用父类中同名的成员变量。
  • 如果实例变量与局部变量重名,可以在实例变量前面加this.进行区别
  • 如果子类实例变量和父类实例变量重名,并且父类的该实例变量在子类仍然可见,在子类中要访问父类声明的实例变量需要在父类实例变量前加super,否则默认访问的是子类自己声明的实例变量
  • 如果父子类实例变量没有重名,只要权限修饰符允许,在子类中完全可以直接访问父类中声明的实例变量,也可以用this.实例访问,也可以用super.实例变量访问
  1. 子类构造器中调用父类构造器。
  • 子类继承父类时,不会继承父类的构造器,只能通过super(形参列表)的方式调用父类指定的构造器
  • 规定super(形参列表)必须声明在构造器的首行
  • 在构造器的首行,this(形参列表)和super(形参列表)只能二选一
  • 如果在子类构造器的首行既没有显示调用this(形参列表),也没有super(形参列表),则子类此构造器默认调用super(),即调用父类中空参的构造器
  • 子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器,只能是这两种情况之一
  • 一个类中声明有n个构造器,最多有n-1个构造器中使用了this(形参列表),则剩下的那个一定使用super(形参列表)

:当父类出现同名成员时,可以用super表明调用的是父类中的成员。super的追溯不仅限于直接父类。super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识。

应用示例

子类中调用父类被重写的方法示例:

public class Phone {
    public void sendMessage(){
        System.out.println("发短信");
    }
    public void call(){
        System.out.println("打电话");
    }
    public void showNum(){
        System.out.println("来电显示号码");
    }
}

public class SmartPhone extends Phone{
    //重写父类的来电显示功能的方法
    public void showNum(){
        //来电显示姓名和图片功能
        System.out.println("显示来电姓名");
        System.out.println("显示头像");
        //保留父类来电显示号码的功能
        super.showNum(); //此处必须加super.,否则就是无限递归,那么就会栈内存溢出
    }
}

总结:

  • 方法前面没有super.和this.:先从子类找匹配方法,如果没有再从直接父类找,再没有继续往上追溯
  • 方法前面由this.:先从子类找匹配方法,如果没有再从直接父类找,再没有继续往上追溯
  • 方法前面由super.:从当前子类的直接父类找,如果没有继续往上追溯

子类中调用父类中同名的成员变量示例:

class Father{
    int a = 10;
    int b = 11;
}
class Son extends Father{
    int a = 20;
    public void test(){
	//子类与父类的属性同名,子类对象中就有两个a
	System.out.println("子类的a:" + a); //20先局部变量找,没有再找本类成员变量
        System.out.println("子类的a:" + this.a); //20先从本类成员变量找
        System.out.println("父类的a:" + super.a); //10直接从父类成员变量找
	//子类与父类的属性不同名,是同一个b
	System.out.println("b = " + b); //11先找局部变量找,没有再找本类成员变量,没有再从父类找
	System.out.println("b = " + this.b); //11先从本类成员变量找,没有再从父类找
	System.out.println("b = " + super.b); //11直接从父类局部变量找
    }
    public void method(int a, int b){
	//子类与父类的属性同名,子类对象中就有两个成员变量a,此时方法中还有一个局部变量a		
	System.out.println("局部变量的a:" + a); //30先找局部变量
        System.out.println("子类的a:" + this.a); //20先从本类成员变量找
        System.out.println("父类的a:" + super.a); //10直接从父类成员变量找
        System.out.println("b = " + b); //13先找局部变量
	System.out.println("b = " + this.b); //11先从本类成员变量找
	System.out.println("b = " + super.b); //11直接从父类局部变量找
    }
}
class Test{
    public static void main(String[] args){
        Son son = new Son();
	son.test();
	son.method(30,13);  
    }
}

总结:

  • 变量前面没有super.和this.:在构造器、代码块、方法中如果出现使用某个变量,先查看是否是当前块声明的局部变量,如果不是局部变量,先从当前执行代码的本类去找成员变量。如果从当前执行代码的本类中没有找到,会往上找父类声明的成员变量(权限修饰符允许在子类中访问的)
  • 变量前面有this.:通过this找成员变量时,先从当前执行代码的本类去找成员变量,如果从当前执行代码的本类中没有找到,会往上找父类声明的成员变量(权限修饰符允许在子类中访问的)
  • 变量前面有super.:通过super找成员变量,直接从当前执行代码的直接父类去找成员变量(权限修饰符允许在子类中访问的),如果直接父类没有,就去父类的父类中找(权限修饰符允许在子类中访问的)

:应该避免子类声明和父类重名的成员变量。

子类构造器中调用父类构造器示例:

class A{
    A(){
        System.out.println("A类无参构造器");
    }
    A(int a){
	System.out.println("A类有参构造器");
    }
}
class B extends A{
    B(){
        super(); //可以省略,调用父类的无参构造
        System.out.println("B类无参构造器");
    }
    B(int a){
	super(a); //调用父类有参构造
	System.out.println("B类有参构造器");
    }
}
class Test8{
    public static void main(String[] args){
        B b1 = new B();
        B b2 = new B(10);
    }
}

this和super:
this:当前对象

  • 在构造器和非静态代码块中,表示正在new的对象
  • 在实例方法中,表示调用当前方法的对象
  • this.成员变量:表示当前对象的某个成员变量,而不是局部变量
  • this.成员方法:表示当前对象的某个成员方法,完全可以省略this.
  • this()或this(实参列表):调用另一个构造器协助当前对象的实例化,只能在构造器首行,只会找本类的构造器,找不到就报错

super:引用父类声明的成员

  • super.成员变量:表示当前对象的某个成员变量,该成员变量在父类中声明的
  • super.成员方法:表示当前对象的某个成员方法,该成员变量在父类中声明的
  • super()或super(实参列表):调用父类的构造器协助当前对象的实例化,只能在构造器首行,只会找直接父类的对应构造器,找不到就报错

static

当编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字参会产出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用,但有时希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间中只有一份,即想让一个成员变量被类的所有实例所共享,就用static修饰即可,称为类变量(或类属性)。

此外在类中声明的实例方法,在类的外面必须先创建对象才能调用,但是有些方法的调用者和当前类的对象无关,这样的方法通常被声明为类方法。这里的类变量、类方法,只需要使用static修饰即可,故也称为静态变量、静态方法。

如何使用

static的使用范围:在java类中,可用static修饰属性、方法、代码块、内部类。

被修饰后的成员具备的特点:随着类的加载而加载,优先于对象存在,修饰的成员被所有对象所共享,访问权限允许时可不创建对象直接被类调用。

静态变量:
语法格式:使用static修饰的成员变量就是静态变量。

[修饰符] class{
    [其他修饰符] static 数据类型 变量名;
}

特点:

  • 静态变量的默认值规则和实例变量一样
  • 静态变量值是所有对象共享
  • 静态变量在本类中,可以在任意方法、代码块、构造器中直接使用
  • 如果权限修饰符允许,在其他类中可以通过类名.静态变量直接访问,也可以通过对象.静态变量的方式访问(更推荐使用类名.静态变量的方式)
  • 静态变量的get/set方法也是静态的,当局部变量与静态变量重名时,使用类名.静态变量进行区分

静态方法:
语法格式:用static修饰的成员方法就是静态方法。

[修饰符] class{
    [其他修饰符] static 返回值类型 方法名(形参列表){
        方法体
    }
}

特点:

  • 静态方法在本类的任意方法、代码块、构造器中都可以直接被调用
  • 只要权限修饰符允许,静态方法在其他类中可以通过类名.静态方法的方式调用,也可以通过对象.静态方法的方式调用(但是更推荐使用类名.静态方法的方式)
  • 在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构
  • 静态方法可以被子类继承,但不能被子类重写
  • 静态方法的调用都只看编译时类型
  • 因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super,如果有重名问题,使用类名.进行区别

应用示例

静态变量示例:

class Chinese{
    String name;
    int age;
    static String nation;
    public Chinese() {
    }
    public Chinese(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Chinese{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nation='" + nation + '\'' +
                '}';
    }
}
public class StaticTest {
    public static void main(String[] args) {
        Chinese c1 = new Chinese("小明",36);
        c1.nation = "中华人民共和国";
        Chinese c2 = new Chinese("小红",66);
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(Chinese.nation);
    }
}

静态方法示例:

public class Father {
    public static void method(){
        System.out.println("Father.method");
    }
    public static void fun(){
        System.out.println("Father.fun");
    }
}
public class Son extends Father{
    //尝试重写静态方法,加上@Override编译报错,去掉Override不报错,但是也不是重写
    public static void fun(){
        System.out.println("Son.fun");
    }
}
public class TestStaticMethod {
    public static void main(String[] args) {
        Father.method();
        Son.method(); //继承静态方法
        Father f = new Son();
        f.method(); //执行Father类中的method
    }
}

final

final意为最终的不可更改的。

如何使用

final修饰类:
表示这个类不能被继承,没有子类,提高安全性,提高程序的可读性,例如String类、System类等。

final修饰方法:
表示这个方法不能被子类重写,例如Object类中的getClass()。

final修饰变量:
final修饰某个变量(成员变量或局部变量),一旦赋值它的值就不能被修改,即常量,常量名建议使用大写字母。如果某个成员变量用final修饰后没有set方法,则必须初始化。

应用示例

final修饰类示例:

final class Eunuch{
}
class Son extends Eunuch{ //错误	
}

final修饰方法示例:

class Father{
    public final void method(){
	System.out.println("father");
    }
}
class Son extends Father{
    public void method(){ //错误
	System.out.println("son");
    }
}

final修饰成员变量示例:

public final class Test {
    public static int totalNumber = 5;
    public final int ID;
    public Test() {
        ID = ++totalNumber; //可在构造器中给final修饰的变量赋值
    }
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.ID);
    }
}

final修饰局部变量示例:

public class TestFinal {
    public static void main(String[] args){
        final int MIN_SCORE ;
        MIN_SCORE = 0;
        final int MAX_SCORE = 100;
        MAX_SCORE = 200; //非法
    }
}

今天的内容就到这里,喜欢的话点个关注吧,下篇见!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农高飞

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值