Java类的定义
在 Java 中定义一个类,需要使用 class 关键字、一个自定义的类名和一对表示程序体的大括号。完整语法如下:
[public][abstract|final]class<class_name>[extends<class_name>][implements<interface_name>] {// 定义属性部分<property_type><property1>;<property_type><property2>;<property_type><property3>;…// 定义方法部分function1();function2();function3();…}
提示:上述语法中,中括号“[]”中的部分表示可以省略,竖线“|”表示“或关系”, 例如 abstract|final,说明可以使用 abstract 或 final 关键字,但是两个关键字不能同时出现。
上述语法中各关键字的描述如下。
public:表示“共有”的意思。如果使用 public 修饰,则可以被其他类和程序访问。每个 Java 程序的主类都必须是 public 类,作为公共工具供其他类和程序使用的类应定义为 public 类。abstract:如果类被 abstract 修饰,则该类为抽象类,抽象类不能被实例化,但抽象类中可以有抽象方法(使用 abstract 修饰的方法)和具体方法(没有使用 abstract 修饰的方法)。继承该抽象类的所有子类都必须实现该抽象类中的所有抽象方法(除非子类也是抽象类)。final:如果类被 final 修饰,则不允许被继承。class:声明类的关键字。class_name:类的名称。extends:表示继承其他类。implements:表示实现某些接口。property_type:表示成员变量的类型。property:表示成员变量名称。function``():表示成员方法名称。
- 类名应该以下划线(_)或字母开头,最好以字母开头。
- 第一个字母最好大写,如果类名由多个单词组成,则每个单词的首字母最好都大写。
- 类名不能为 Java 中的关键字,例如 boolean、this、int 等。
- 类名不能包含任何嵌入的空格或点号以及除了下划线(_)和美元符号($)字符之外的特殊字符。
示例
public class Person {private String name; // 姓名private int age; // 年龄public void tell() {// 定义说话的方法System.out.println(name+"今年"+age+"岁!");}}
Java类的属性
成员变量的定义和声明
在 Java 中类的成员变量定义了类的属性。
例如,一个学生类中一般需要有姓名、性别和年龄等属性,这时就需要定义姓名、性别和年龄 3 个属性。
声明成员变量的语法如下:
[public|protected|private][static][final]<type><variable_name>
各参数的含义如下。
public、protected、private:用于表示成员变量的访问权限。static:表示该成员变量为类变量,也称为静态变量。final:表示将该成员变量声明为常量,其值无法更改。type:表示变量的类型。variable_name:表示变量名称。
可以在声明成员变量的同时对其进行初始化,如果声明成员变量时没有对其初始化,则系统会使用默认值初始化成员变量。
初始化的默认值如下:
- 整数型(byte、short、int 和 long)的基本类型变量的默认值为 0。
- 单精度浮点型(float)的基本类型变量的默认值为 0.0f。
- 双精度浮点型(double)的基本类型变量的默认值为 0.0d。
- 字符型(char)的基本类型变量的默认值为 “\u0000”。
- 布尔型的基本类型变量的默认值为 false。
- 数组引用类型的变量的默认值为 null。如果创建了数组变量的实例,但没有显式地为每个元素赋值,则数组中的元素初始化值采用数组数据类型对应的默认值。
定义类的成员变量的示例如下:
public class Student {public String name; // 姓名final int sex = 0; // 性别:0表示女孩,1表示男孩private int age; // 年龄}
上述示例的 Student 类中定义了 3 个成员变量:
String 类型的 name、
int 类型的 sex 和 int 类型的 age。
其中,name 的访问修饰符为 public,初始化值为 null;
sex 的访问修饰符为 friendly(默认),初始化值为 0,表示性别为女,且其值无法更改;
age 的访问修饰符为 private,初始化值为 0。
Java成员方法
声明成员方法可以定义类的行为,行为表示一个对象能够做的事情或者能够从一个对象取得的信息。
类的各种功能操作都是用方法来实现的,属性只不过提供了相应的数据。
一个完整的方法通常包括方法名称、方法主体、方法参数和方法返回值类型,其结构如图 1 所示。
成员方法一旦被定义,便可以在程序中多次调用,提高了编程效率。声明成员方法的语法格式如下:
public class Test {[public|private|protected][static]<void|return_type><method_name>([paramList]) {// 方法体}}
注意:上述语法中,中括号“[]”中的部分表示可以省略,竖线“|”表示“或”,例如 public|private,说明可以使用 public 或 private 关键字,但是两个关键字不能同时出现。
paramList 表示参数列表,这些变量都要有自己的数据类型,可以是原始数据类型,也可以是复杂数据类型,一个方法主要依靠参数来传递消息。方法主体是方法中执行功能操作的语句。其他各修饰符的含义如下。
public、private、protected:表示成员方法的访问权限。static:表示限定该成员方法为静态方法。final:表示限定该成员方法不能被重写或重载。abstract:表示限定该成员方法为抽象方法。抽象方法不提供具体的实现,并且所属类型必须为抽象类。
Java匿名对象
标准格式如下:
类名称 对象名 = new 类名称();
每次 new 都相当于开辟了一个新的对象,并开辟了一个新的物理内存空间。如果一个对象只需要使用唯一的一次,就可以使用匿名对象,匿名对象还可以作为实际参数传递。
匿名对象就是没有明确的给出名字的对象,是对象的一种简写形式。一般匿名对象只使用一次,而且匿名对象只在堆内存中开辟空间,而不存在栈内存的引用。
示例
public class Person {public String name; // 姓名public int age; // 年龄// 定义构造方法,为属性初始化public Person(String name, int age) {this.name = name;this.age = age;}// 获取信息的方法public void tell() {System.out.println("姓名:" + name + ",年龄:" + age);}public static void main(String[] args) {new Person("张三", 30).tell(); // 匿名对象}}
在以上程序的主方法中可以发现,直接使用了“``new Person("张三",30)``”语句,这实际上就是一个匿名对象,与之前声明的对象不同,此处没有任何栈内存引用它,所以此对象使用一次之后就等待被 GC(垃圾收集机制)回收。
Java注释
1. 类注释
类注释一般必须放在所有的“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 标记,由@和标记类型组成,缺一不可。@和标记类型之间有时可以用空格符分隔,但是不推荐用空格符分隔,这样容易出错。
2. 方法注释
方法注释必须紧靠在方法定义的前面,主要声明方法参数、返回值、异常等信息。除了可以使用通用标签外,还可以使用下列的以@开始的标签。
- @param 变量描述:对当前方法的参数部分添加一个说明,可以占据多行。一个方法的所有 @param 标记必须放在一起。
- @return 返回类型描述:对当前方法添加返回值部分,可以跨越多行。
- @throws 异常类描述:表示这个方法有可能抛出异常。
- /**
- @param num1: 加数1
- @param num2: 加数2
- @return: 两个加数的和
- */
- public int add(int num1,int num2) {
- int value = num1 + num2;
- return value;
- }
3. 字段注释
字段注释在定义字段的前面,用来描述字段的含义。下面是一个字段注释的例子。
- /**
- 用户名
- */
- public String name;
也可以使用如下格式:
- /*用户名/
- public String name;
Java访问控制修饰符
访问控制符是一组限定类、属性或方法是否可以被程序里的其他部分访问和调用的修饰符。
类的访问控制符只能是空或者 public,方法和属性的访问控制符有 4 个,分别是 public、 private、protected 和 friendly,其中 friendly 是一种没有定义专门的访问控制符的默认情况。
访问控制修饰符的权限如表所示。
| 访问范围 | private | friendly(默认) | protected | public |
|---|---|---|---|---|
| 同一个类 | 可访问 | 可访问 | 可访问 | 可访问 |
| 同一包中的其他类 | 不可访问 | 可访问 | 可访问 | 可访问 |
| 不同包中的子类 | 不可访问 | 不可访问 | 可访问 | 可访问 |
| 不同包中的非子类 | 不可访问 | 不可访问 | 不可访问 | 可访问 |
访问控制在面向对象技术中处于很重要的地位,合理地使用访问控制符,可以通过降低类和类之间的耦合性(关联性)来降低整个项目的复杂度,也便于整个项目的开发和维护。在 Java 语言中,访问控制修饰符有 4 种。
private
用 private 修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用。因此,private 修饰符具有最高的保护级别。例如,设 PhoneCard 是电话卡类,电话卡都有密码,因此该类有一个密码域,可以把该类的密码域声明为私有成员。friendly(默认)
如果一个类没有访问控制符,说明它具有默认的访问控制特性。这种默认的访问控制权规定,该类只能被同一个包中的类访问和引用,而不能被其他包中的类使用,即使其他包中有该类的子类。这种访问特性又称为包访问性(package private)。
同样,类内的成员如果没有访问控制符,也说明它们具有包访问性,或称为友元(friend)。定义在同一个文件夹中的所有类属于一个包,所以前面的程序要把用户自定义的类放在同一个文件夹中(Java 项目默认的包),以便不加修饰符也能运行。
- protected
用保护访问控制符 protected 修饰的类成员可以被三种类所访问:该类自身、与它在同一个包中的其他类以及在其他包中的该类的子类。使用 protected 修饰符的主要作用,是允许其他包中它的子类来访问父类的特定属性和方法,否则可以使用默认访问控制符。 - public
当一个类被声明为 public 时,它就具有了被其他包中的类访问的可能性,只要包中的其他类在程序中使用 import 语句引入 public 类,就可以访问和引用这个类。
Java方法的可变参数
声明可变参数的语法格式如下:
public static void methodName({paramList},paramType... paramName)
其中,methodName表示方法名称;paramList表示方法的固定参数列表;paramType表示可变参数的类型;… 是声明可变参数的标识;paramName表示可变参数名称。
示例
public class StudentTestMethod {// 定义输出考试学生的人数及姓名的方法public void print(String... names) {int count = names.length; // 获取总个数System.out.println("本次参加考试的有"+count+"人,名单如下:");for(int i = 0;i < names.length;i++) {System.out.println(names[i]);}}public static void main(String[] args) {// TODO Auto-generated method stubStudentTestMethod student = new StudentTestMethod();student.print("张强","李成","王勇"); // 传入3个值student.print("马丽","陈玲");}}//-----------------------运行输出结果如下:-----------------------------//本次参加考试的有3人,名单如下://张强//李成//王勇//本次参加考试的有2人,名单如下://马丽//陈玲
Java构造方法
构造方法是类的一种特殊方法,用来初始化类的一个新的对象,在创建对象(new 运算符)之后自动调用。
Java 中的每个类都有一个默认的构造方法,并且可以有一个以上的构造方法。
Java 构造方法有以下特点:
- 方法名必须与类名相同
- 可以有 0 个、1 个或多个参数
- 没有任何返回值,包括 void
- 默认返回类型就是对象类型本身
- 只能与 new 运算符结合使用
注意:构造方法不能被 static、final、synchronized、abstract 和 native(类似于 abstract)修饰。 构造方法用于初始化一个新对象,所以用 static 修饰没有意义。 构造方法不能被子类继承,所以用 final 和 abstract 修饰没有意义。 多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 修饰没有必要。
构造方法的语法格式如下:
class class_name {public class_name(){} // 默认无参构造方法public ciass_name([paramList]){} // 定义构造方法…// 类主体}
在一个类中,与类名相同的方法就是构造方法。每个类可以具有多个构造方法,但要求它们各自包含不同的方法参数。
示例
public class MyClass {private int m; // 定义私有变量MyClass() {// 定义无参的构造方法m = 0;}MyClass(int m) {// 定义有参的构造方法this.m = m;}}
该示例定义了两个构造方法,分别是无参构造方法和有参构造方法。在一个类中定义多个具有不同参数的同名方法,这就是方法的重载。这两个构造方法的名称都与类名相同,均为 MyClass。在实例化该类时可以调用不同的构造方法进行初始化。
注意:类的构造方法不是要求必须定义的。如果在类中没有定义任何一个构造方法,则 Java 会自动为该类生成一个默认的构造方法。默认的构造方法不包含任何参数,并且方法体为空。 如果类中显式地定义了一个或多个构造方法,则 Java 不再提供默认构造方法。
Java 代码块
代码块是类的成分之一:成员变量,方法,构造器,代码块,内部类。
在Java中,使用 { }括起来的代码被称为代码块(Code block)
1 代码块的分类
根据其位置和声明的不同,可以分为:
- 局部代码块:用于限定变量生命周期,及早释放,提高内存利用率。
- 静态代码块:主要用于对静态属性进行初始化。
- 实例(构造)代码块:调用构造方法都会执行,并且在构造方法前执行。
- 同步代码块:一种多线程保护机制。
2 局部代码块
在方法中出现,可以限定变量生命周期,及早释放,提高内存利用率。
示例代码
public class Test1{public static void main(String[] args) {//局部代码块{int n = 100;}// 局部代码块中声明的变量在代码块外部访问不到!// System.out.println(n);}}
<br />
3 静态代码块
必须有static修饰,必须放在类下。与类一起加载执行。并且静态代码块执行一次
示例代码
public class Test2 {
public static String name;
// 静态代码块
static {
// 初始化静态资源
name = "张三";
System.out.println("静态代码块执行...");
}
public static void main(String[] args) {
System.out.println("main方法执行...");
System.out.println(name);
}
}
示例输出
静态代码块执行... main方法执行... 张三
<br />**特点**
- 每次执行类,加载类的时候都会先执行静态代码块一次。
- 静态代码块是自动触发执行的,只要程序启动静态代码块就会先执行一次。
- 在启动程序之前可以做资源的初始化,一般用于初始化静态资源。
4 实例代码块(构造代码块)
没有static修饰,必须放在类下。与对象初始化一起加载,即每次调用构造方法都会执行,并且在构造方法前执行。
示例代码
public class Test3{
private String name;
// 实例代码块。 无static修饰。
{
System.out.println("实例代码块执行...");
name = "张三";
}
// 构造器
public Test3(){
System.out.println("无参构造方法执行...");
}
// 有参数构造器
public Test3(String name){
System.out.println("有参构造方法执行...");
this.name = name;
}
public static void main(String[] args) {
Test3 t1 = new Test3();
Test3 t2 = new Test3("李四");
System.out.println(t1.name + t2.name);
}
}
<br />**示例输出**
实例代码块执行... 无参构造方法执行... 实例代码块执行... 有参构造方法执行... 张三李四
特点
- 无static修饰。属于对象,与对象的创建一起执行的。
- 每次调用构造器初始化对象,实例代码块都要自动触发执行一次。
- 实例代码块实际上是提取到每一个构造器中去执行的。
- 实例代码块中的内容在构造方法前执行。
静态代码块、构造代码块、构造函数执行顺序
父类静态代码块 > 子类静态代码块 > main()方法 > 父类代码块 > 父类构造器 > 子类代码块 > 子类构造器
5 同步代码块
同步代码块指的是被Java中Synchronized关键词修饰的代码块,在Java中,Synchronized关键词不仅仅可以用来修饰代码块,与此同时也可以用来修饰方法,是一种线程同步机制,被Synchronized关键词修饰的代码块会被加上内置锁。
代码示例
public class Test4 implements Runnable {
@Override
public void run() {
synchronized (CodeBlock.class) {
System.out.print("同步代码块...");
}
}
public static void main(String[] args) {
CodeBlock a = new CodeBlock();
CodeBlock b = new CodeBlock();
new Thread(a).start();
new Thread(b).start();
}
}
