Java基础(3)

Java类和对象

Java注释:类、方法和字段注释

类注释

类注释一般必须放在所有的“import”语句之后,类定义之前,主要声明该类可以做什么,以及创建者、创建日期、版本和包名等一些信息。以下是一个类注释的模板

/**
 * @projectName(项目名称): project_name
 * @package(包): package_name.file_name
 * @className(类名称): type_name
 * @description(类描述): 一句话描述该类的功能
 * @author(创建人): user 
 * @createDate(创建时间): datetime  
 * @updateUser(修改人): user 
 * @updateDate(修改时间): datetime
 * @updateRemark(修改备注): 说明本次修改内容
 * @version(版本): v1.0
 */

提示:以上以@开头的标签为 Javadoc 标记,由@和标记类型组成,缺一不可。@和标记类型之间有时可以用空格符分隔,但是不推荐用空格符分隔,这样容易出错

一个类注释的创建人、创建时间和描述是不可缺少的。下面是一个类注释的例子

/**
 * @author: zhangsan
 * @createDate: 2018/10/28
 * @description: this is the student class.
 */
public class student{
    .................
}

注意:没有必要在每一行的开始用*。例如,以下注释同样是合法的:

/**
   @author: zhangsan
   @createDate: 2018/10/28
   @description: this is the student class.
 */
public class student{
    .................
}

方法注释

方法注释必须紧靠在方法定义的前面,主要声明方法参数、返回值、异常等信息。除了可以使用通用标签外,还可以使用下列的以@开始的标签

  • @param 变量描述:对当前方法的参数部分添加一个说明,可以占据多行。一个方法的所有 @param 标记必须放在一起
  • @return 返回类型描述:对当前方法添加返回值部分,可以跨越多行
  • @throws 异常类描述:表示这个方法有可能抛出异常。有关异常的详细内容将在第 10 章中讨论

下面是一个方法注释的例子

/**
 * @param num1: 加数1
 * @param num2: 加数2
 * @return: 两个加数的和
 */
public int add(int num1,int num2) {
    int value = num1 + num2;
    return value;
}

以上代码的 add() 方法中声明了两个形参,并将它们两个的和作为返回值返回。

为类的构造方法添加注释时,一般声明该方法的参数信息,代码如下

public class Student {
   String name;
   int age;
   /**
    * @description: 构造方法
    * @param name: 学生姓名
    * @param age: 学生年龄
    */
   public Student(String name,int age) {
    this.name = name;
    this.age = age;
   }
}

字段注释

字段注释在定义字段的前面,用来描述字段的含义。下面是一个字段注释的例子

/**
 * 用户名
 */
public String name;

也可以使用如下格式:

/**用户名*/
public String name;

类的静态代码块

在java类中(方法中不能存在静态代码块)使用static关键字和{}声明的代码块

public class CodeBlock{
     static{
        System.out.println("静态代码块");  
}      
}

执行时机:静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数。如果一个类中有多个静态代码块,就会按照书写的顺序执行

静态代码块的作用:一般情况下,如果有些代码需要在项目启动的时候执行,这时就需要静态代码快,比如一个项目启动需要加载很多配置文件等资源,就可以都放在静态代码块中

静态代码块不能存在于任何方法体中,静态代码块是在类加载的时候就运行了

  • 对于普通方法,由于普通方法是通过加载类,然后new出实例化对象,通过对象才能运行这个方法,而静态代码块只需要加载类之后就能运行了
  • 对于静态方法,在类加载的时候,静态方法就已经加载了,但是我们必须通过类名或者对象名才能进行访问,也就是说相对于静态代码块,静态代码块是主动运行的,而静态方法是被动运行的
  • 不管哪种方法,我们需要明确的是静态代码块的存在在类加载的时候就自动运行了,而放在不管是普通方法中还是静态方法中,都是不能自动运行的

静态代码块不能访问普通代变量

Java中静态导入的使用

要使用静态成员(方法和变量)我们必须给出提供这个静态成员的类

使用静态导入可以使被导入类的静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名。

静态导入也是JDK5.0引入的新特性,下面以实例来说明静态导入的用法,比如先在一个包中定义一个这样的类:

package com.example.learnjava;

public class Common
{

    public static final int AGE = 10;
    public static void output()
    {
        System.out.println("Hello World!");
    }
}

在另一个包中使用时,如果不用静态导入,是这样用的:

package com.example.learnjava2;

import com.example.learnjava.Common;

public class StaticImportTest
{
    public static void main(String[] args)
    {
        int a = Common.AGE;
        System.out.println(a);
        
        Common.output();
    }

}

前面加入了导入语句,将Common类导入,使用其中的静态成员变量和静态方法时需要加上类名。

使用静态导入

静态导入的语法是:

  • import static 包名.类名.静态成员变量;
  • import static 包名.类名.静态成员函数;

如前面的程序使用静态导入后:

package com.example.learnjava2;

import static com.example.learnjava.Common.AGE;
import static com.example.learnjava.Common.output;

public class StaticImportTest
{
    public static void main(String[] args)
    {
        int a = AGE;
        System.out.println(a);
        
        output();
    }

}

缺点:过度地使用静态导入会在一定程度上降低代码的可读性。

Java方法的可变参数

在具体实际开发过程中,有时方法中参数的个数是不确定的。为了解决这个问题,在 J2SE 5.0 版本中引入了可变参数的概念。

声明可变参数的语法格式如下:

methodName({paramList},paramType…paramName)

其中,methodName 表示方法名称;paramList 表示方法的固定参数列表;paramType 表示可变参数的类型;… 是声明可变参数的标识;paramName 表示可变参数名称。

注意:可变参数必须定义在参数列表的最后。

示例代码如下

public class Test31 {
	public void print(String ...names) {
		for(String name:names) {
			System.out.println(name);
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Test31().print("zeng1", "zeng2");
		new Test31().print("zeng1", "zeng2", "zeng3", "zeng4");
	}
}

Java包

包的 3 个作用如下:

  • 区分相同名称的类。
  • 能够较好地管理大量的类。
  • 控制访问范围。

包定义

定义包语法格式如下:

package 包名;

Java 包的命名规则如下:

  • 包名全部由小写字母(多个单词也全部小写)
  • 如果包名包含多个层次,每个层次用“.”分割
  • 包名一般由倒置的域名开头,比如 com.baidu,不要有 www
  • 自定义包不能 java 开头

包导入

为了简化编程,Java 引入了 import 关键字,import 可以向某个 Java 文件中导入指定包层次下的某个类或全部类。import 语句位于 package 语句之后,类定义之前。一个 Java 源文件只能包含一个 package 语句,但可以包含多个 import 语句。

使用 import 导入单个类的语法格式如下:

import 包名+类名;

也可以使用*号

import example.*;

提示:使用星号(*)可能会增加编译时间,特别是引入多个大包时,所以明确的导入你想要用到的类是一个好方法,需要注意的是使用星号对运行时间和类的大小没有影响。

系统包

说明
java.langJava 的核心类库,包含运行 Java 程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、异常处理和线程类等,系统默认加载这个包
java.ioJava 语言的标准输入/输出类库,如基本输入/输出流、文件输入/输出、过滤输入/输出流等
java.util包含如处理时间的 Date 类,处理动态数组的 Vector 类,以及 Stack 和 HashTable 类
java.awt构建图形用户界面(GUI)的类库,低级绘图操作 Graphics 类、图形界面组件和布局管理(如 Checkbox 类、Container 类、LayoutManger 接口等),以及用户界面交互控制和事件响应(如 Event 类)
java.awt.image处理和操纵来自网上的图片的 Java 工具类库
java.wat.peer很少在程序中直接用到,使得同一个 Java程序在不同的软硬件平台上运行
java.net实现网络功能的类库有 Socket 类、ServerSocket 类
java.lang.reflect提供用于反射对象的工具
java.util.zip实现文件压缩功能
java.awt.datatransfer处理数据传输的工具类,包括剪贴板、字符串发送器等
java.sql实现 JDBC 的类库
java.rmi提供远程连接与载入的支持
java. security提供安全性方面的有关支持

Java使用自定义包、Java递归、Java面向对象概述

新建一个包com.zengraoli.test2,有Student类,内容如下

package com.zengraoli.test2;
public class Student {
	public void Hello() {
		System.out.println("hello world.");
	}
}

再建一个包com.zengraoli.test,带有main函数,去引入并调用Student类的方法

package com.zengraoli.test;
import com.zengraoli.test2.Student;
public class Test7 {
	public static void main(String[] args) {
		Student stu = new Student();
		stu.Hello();
	}
}

递归算法

看一下即可:Java递归算法

Java类的封装

封装的特点:

  • 只能通过规定的方法访问数据。
  • 隐藏类的实例细节,方便修改和实现。

实现封装的具体步骤如下:

  • 修改属性的可见性来限制对属性的访问,一般设为 private。
  • 为每个属性创建一对赋值(setter)方法和取值(getter)方法,一般设为public,用于属性的读写。
  • 在赋值和取值方法中,加入属性控制语句(对属性值的合法性进行判断)。

Java继承简明教程

Java 的继承通过 extends 关键字来实现,子类继承父类的语法格式如下:

修饰符 class class_name extends extend_class {
    // 类的主体
}

使用继承的注意点:

  • 子类一般比父类包含更多的属性和方法。
  • 父类中的 private 成员在子类中是不可见的,因此在子类中不能直接使用它们。
  • 父类和其子类间必须存在“是一个”即“is-a”的关系,否则不能用继承。但也并不是所有符合“is-a”关系的都应该用继承。例如,正方形是一个矩形,但不能让正方形类来继承矩形类,因为正方形不能从矩形扩展得到任何东西。正确的继承关系是正方形类继承图形类。
  • Java 只允许单一继承(即一个子类只能有一个直接父类),C++可以多重继承(即一个子类有多个直接父类)。

在面向对象语言中,继承是必不可少的、非常优秀的语言机制,它有如下优点:

  • 实现代码共享,减少创建类的工作量,使子类可以拥有父类的方法和属性。
  • 提高代码维护性和可重用性。
  • 提高代码的可扩展性,更好的实现父类的方法。

Java Super关键字

由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字。super 可以用来访问父类的构造方法、普通方法和属性

super 关键字的功能

主要有两点

  • 在子类的构造方法中显式的调用父类构造方法
  • 访问父类的成员方法和变量

super和this的区别

this 指的是当前对象的引用,super 是当前对象的父对象的引用

super 关键字的用法:

  • super.父类属性名:调用父类中的属性
  • super.父类方法名:调用父类中的方法
  • super():调用父类的无参构造方法
  • super(参数):调用父类的有参构造方法

如果构造方法的第一行代码不是 this() 和 super(),则系统会默认添加 super()

this 关键字的用法:

  • this.属性名:表示当前对象的属性
  • this.方法名(参数):表示调用当前对象的方法

关于 Java super 和 this 关键字的异同,可简单总结为以下几条。

  • 子类和父类中变量或方法名称相同时,用 super 关键字来访问。可以理解为 super是指向自己父类对象的一个指针。在子类中调用父类的构造方法。
  • this 是自身的一个对象,代表对象本身,可以理解为 this是指向对象本身的一个指针。在同一个类中调用其它方法。
  • this 和 super 不能同时出现在一个构造方法里面,因为 this必然会调用其它的构造方法,其它的构造方法中肯定会有 super语句的存在,所以在同一个构造方法里面有相同的语句,就失去了语句的意义,编译器也不会通过。
  • this( ) 和 super( )都指的是对象,所以,均不可以在static环境中使用,包括static 变量、static 方法和 static 语句块。
  • 从本质上讲,this 是一个指向对象本身的指针, 然而 super 是一个 Java 关键字。

Java方法重载

Java 允许同一个类中定义多个同名方法,只要它们的形参列表不同即可。如果同一个类中包含了两个或两个以上方法名相同的方法,但形参列表不同,这种情况被称为方法重载(overload)

比如下面的函数都是重载

public void println(int i){…}
public void println(double d){…}
public void println(String s){…}

Java方法重写

在子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写(override),又称为方法覆盖。当父类中的方法无法满足子类需求或子类具有特有功能的时候,需要方法重写

在重写方法时,需要遵循下面的规则:

  • 参数列表必须完全与被重写的方法参数列表相同
  • 返回的类型必须与被重写的方法的返回类型相同(Java1.5版本之前返回值类型必须一样,之后的 Java 版本放宽了限制,返回值类型必须小于或者等于父类方法的返回值类型)
  • 访问权限不能比父类中被重写方法的访问权限更低(public>protected>default>private)
  • 重写方法一定不能抛出新的检査异常或者比被重写方法声明更加宽泛的检査型异常。例如,父类的一个方法声明了一个检査异常IOException,在重写这个方法时就不能抛出Exception,只能拋出 IOException 的子类异常,可以抛出非检査异常

另外还要注意以下几条:

  • 重写的方法可以使用 @Override 注解来标识。
  • 父类的成员方法只能被它的子类重写。
  • 声明为 final 的方法不能被重写。
  • 声明为 static 的方法不能被重写,但是能够再次声明。
  • 构造方法不能被重写。
  • 子类和父类在同一个包中时,子类可以重写父类的所有方法,除了声明为private和final 的方法。
  • 子类和父类不在同一个包中时,子类只能重写父类的声明为 public 和 protected 的非 final 方法。
  • 如果不能继承一个方法,则不能重写这个方法。

Java多态

对面向对象来说,多态分为编译时多态和运行时多态。其中编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的方法。通过编译之后会变成两个不同的方法,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是大家通常所说的多态性

Java 实现多态有 3 个必要条件:继承、重写和向上转型。只有满足这 3 个条件,开发人员才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而执行不同的行为

  • 继承:在多态中必须存在有继承关系的子类和父类。
  • 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
  • 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。

参考链接


版权声明:本文为zengraoli原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。