1.包的概念
1)package
- 作用:避免类的命名冲突
- 包名可以有层次结构,类的全称:包名.类名
- 同包中的类不能同名
- 建议:包名所有字母都小写
- package语句必须写在Java源文件的最开始处
定义包名:
package org.apache.commons.lang
在实际应用中,包的命名常常是多层次的,因为如果各个公司或开发组织的程序员都随心所欲的命名包名的话,依然不能从根本上解决命名冲突的问题,不利于软件的复用。如上案例,org.apache表示公司或组织的信息(是这个公司或组织域名的反写),commons表示项目的名称信息,lang表示模块的名称信息。
2)import
- 同包中的类可以直接访问
- 不同包中的类不能直接访问,若想访问有以下两种方式:
-
- a.先import后在访问,import 包名.类名——建议
- b.类的全称,包名.类名——太繁琐,不建议
-
不同包的两种访问方式:
import org.test.core.Point;
Point p = new Point();
或者
org.test.core.Point p = new org.test.core.Point();
有时在import语句中也可以使用“*”符号,例如:
import org.test.core.*;
如上import语句意味着该包中所有类的全称,即在该源文件中,使用所有包名为org.test.core的类都可以仅仅通过类名来访问。需要注意的是,“import 包名.*”语句并不包含该名的子包中的类(比如org.test中的类不包含)。
Tips:在Eclipse中,可以使用“CTRL+SHIFT+O”自动完成import语句。
2.访问控制修饰符
2.1 封装的意义
- 降低代码出错的可能性,更便于维护
- 当内部实现细节改变时,只要保证对外的功能定义不变,其他的模块不需要更改
2.2 访问控制修饰符
- public:公共的,任何类
- private:私有的,本类
- protected:受保护的,本类、子类、同包类
- 默认的:什么也不写,本类、同包类
修饰符 | 本类 | 同一个包中的类 | 子类 | 其他类 |
public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
protected | 可以访问 | 可以访问 | 可以访问 | 不能访问 |
默认 | 可以访问 | 可以访问 | 不能访问 | 不能访问 |
private | 可以访问 | 不能访问 | 不能访问 | 不能访问 |
注意:类的访问控制修饰符只能是public或默认的,类中的成员变量如上4种都可以。
3. static与final
3.1 static:静态的
3.1.1 static修饰成员变量
static可以修饰成员变量,它所修饰的成员变量不属于对象的数据结构,而是属于类的变量,通常通过类名来引用static成员。当创建对象后,成员变量存储在堆中,而static成员变量和类的信息一起存储在方法区中,一个类的static成员变量只有“一份”(存储在方法区中),无论该类创建了多少对象。
1)静态变量:
1.1)由static修饰的
1.2)属于类的,存在方法区中,只有一份
1.3)常常通过类名.变量来访问
1.4)何时用:所有对象所共享的数据(图片、音频、视频等)
案例1:static修饰成员变量
public class StaticVarDemo {
public static void main(String[] args){
Student s1 = new Student(2);
Student s2 = new Student(3);
// s1.age = 5; 编译错误,private修饰,无法访问
}
}
class Student{
private int age;
private static int numOfStudent;
public Student(int age){
this.age = age;
System.out.println(++numOfStudent);
}
}
以上代码运行结果:
1
2
以上运行结果分析:如上代码,声明两个Student类对象后,numOfStudent的值为2。当声明第一个Student类对象后,numOfStudent值增1变为1(默认为0),声明第二个Student对象后,因为numOfStudent存在方法区中只有一份,所以其值在刚刚的1的基础上变为2。
3.1.2 static修饰方法
通常的方法都会涉及到对具体对象的操作,这些方法在调用时,需要隐式的传递对象的引用(this),而static修饰的方法则不需要对某些对象进行操作,其运行结果仅仅与输入的参数有关,调用时直接类名引用即可,如下代码:
double c = Math.sqrt(3.0*3.0);
上面的方法在调用时,没有隐式的传递对象引用,因此在static方法中是不可以使用this关键字的。另外,由于static在调用时没有具体的对象,因此在static方法中不能对非static成员(对象成员)进行访问。
static方法的作用在于提供一些“工具方法”和“工厂方法”等,如下的一些工具方法,只是完成某一功能,不需要传递this。
RandomUtils.nextInt()
StringUtils.leftPad(String str,int size,char padChar)
2)静态方法:
2.1)由static修饰的
2.2)属于类的,存在方法区中,只有一份
2.3)常常通过类名.方法来访问
2.4)静态方法没有隐式的this传递,静态方法中不能直接访问实例成员
2.5)何时用:方法的操作仅与参数相关而与对象无关
3.1.3 static块
static块为属于类的代码块,在类加载期间执行的代码块,只执行一次,可以用来在软件中还在静态资源(图像、音频等)。
案例2:静态块演示
public class StaticBlockDemo {
public static void main(String[] args){
Foo foo = new Foo();
}
}
class Foo{
public Foo(){
System.out.println("Foo()");
}
static{
//类加载期间,只执行一次
System.out.println("Load Foo.class");
}
}
/*
运行结果:
Load Foo.class
Foo()
*/
在Foo类加载时,先运行静态块,而后执行构造方法,即:static块是在创建对象之前执行的。
3)静态块:
3.1)属于类的,在类被加载期间自动执行,因为类只被加载一次,所以静态块也只执行一次
3.2)何时用:初始化/加载静态资源(图片、音频、视频等)
3.2 final:最终的、不可变的
- 修饰变量:变量不能被改变
- 修饰方法:方法不能被重写
- 修饰类:类不能被继承
3.2.1 final修饰变量
final关键字修饰变量,意为不可改变的,final可以修饰成员变量,也可以修饰局部变量,当final修饰成员变量时,可以有两种初始化方式:
- 声明同时初始化
- 构造函数中初始化
final关键字修饰局部变量,在使用之前初始化即可。
public class FinalVarDemo {
private final int no=100; //final成员变量声明时初始化
public static void main(String[] args){
// no = 99; 编译错误,因为final变量不可被改变
}
}
3.2.2 final修饰方法
final关键字修饰方法不可以被重写,使一个方法不能被重写的意义在于:防止子类在定义新方法时造成的“不经意”重写,如下案例。
class Car{
//点火
public void fire(){...}
}
class Tank extends Car{
//开炮
public void fire(){...}
}
为避免上述情况,可以将Car类方法声明为final的,这样该方法就不能被子类重写。
class Car{
//点火
public final void fire(){}
}
class Tank extends Car{
//开炮
// public void fire(){} 编译错误,不能被重写
}
3.2.3 final修饰类
final关键字修饰的类不可以被继承。使一个类不能被继承的意义在于:可以保护类不被继承修改,可以控制滥用继承对系统造成的危害。在JDK中的一些基础类库被定义为final的,如:String、Math、Integer、Double等。自己定义的类也可以声明为final的。
final class Foo{}
class Goo extends Foo{} //编译错误,final修饰的类不可以被继承
3.3 static final常量
- 必须声明同时初始化
- 通过类名来访问,不能被改变
- 常量名所有的字母都大写,多个单词用_分隔(如STUDENT_NAME)
- 编译器在编译时会将常量直接替换为具体的值,效率高
public class FinalFunctionDemo {
public static void main(String[] args){
System.out.println(Soo.NUM); //使用类名. 来访问
//代码编译时,会替换为:System.out.println(100);
}
}
class Soo{
public static final int NUM=100;
}
//运行结果:100
4. 案例演示
案例3:final演示
//演示final修饰变量 /* * final 修饰成员变量,只有两种初始化方法: * 1)声明的同时初始化 * 2)在构造方法中初始化 * final修饰局部变量,只要在用之前初始化即可 */ class Aoo{ final int a = 5; final int b; Aoo(){ b = 6; } void show(){ final int c; // a = 55; //编译错误,final的变量不可被改变 } } //演示final修饰方法 class Boo{ final void show(){} void say(){} } class Coo extends Boo{ // void show(){} //编译错误,final修饰的方法不能被重写 void say(){} } //演示final修饰类 final class Doo{ } //class Eoo extends Doo{} //编译错误,final修饰的类不能被继承 class Foo{} final class Goo extends Foo{} //final修饰的类可以继承别的类
案例4:static演示
public class StaticDemo {
public static void main(String[] args){
Joo o1 = new Joo();
o1.show();
/*
输出:
a=1
b=1
*/
Joo o2 = new Joo();
o2.show();
System.out.println("Joo.b="+Joo.b); //建议类名. 来访问
System.out.println("o1.b="+o1.b); //不建议
System.out.println("o2.b="+o2.b); //不建议
/*
*输出:
*a=1
*b=2
*Joo.b=2
*o1.b=2
*o2.b=2
*/
Koo.test();
/*
* 输出:
* 0
*/
Loo o3 = new Loo();
Loo o4 = new Loo();
/*
* 输出:
* 静态块 //静态块只执行一次
*构造方法
*构造方法
*/
}
}
class Loo{ //演示静态块
static{
System.out.println("静态块");
}
Loo(){
System.out.println("构造方法");
}
}
class Koo{ //演示静态方法
int a;
static int b;
void show(){ //有隐式this
System.out.println(a); //this.a
System.out.println(b); //Koo.b
}
static void test(){ //没有隐式this
/*没有this意味着没有对象,而实例成员必须通过对象. 来访问
所以静态方法中不能直接访问实例成员
System.out.println(a); 编译错误
*/
System.out.println(b); //Koo.b
}
}
class Joo{ //演示静态变量
int a; //实例变量
static int b; //静态变量
Joo(){
a++;
b++;
}
void show(){
System.out.println("a="+a);
System.out.println("b="+b);
}
}
/*
输出结果:
a=1
b=1
a=1
b=2
Joo.b=2
o1.b=2
o2.b=2
0
静态块
构造方法
构造方法
*/
案例5:static final的演示
public class StaticFinalDemo { public static void main(String[] args){ System.out.println(Hoo.PI); //3.14 通过类名点 来访问 // Hoo.PI = 3.1415926; //编译错误,常量不能被改变 Ioo o1 = new Ioo(); o1.count = 50; Ioo o2 = new Ioo(); System.out.println(o2.count); //50 静态变量只有一份 /* * 1)加载Ioo.class到方法区中 * 2)静态变量count存储到方法区中 * 3)到方法区中获取count并输出 */ System.out.println(Ioo.count); /* * 编译器在编译时会将常量直接替换为具体的值---效率高 */ System.out.println(Ioo.NUM); //5 } } class Ioo{ public static final int NUM = 5; //常量 public static int count = 5; //静态变量 } class Hoo{ public static final double PI = 3.14; public static final int DOUBLE_NUM = 5; // public static final int NUMBER; //编译错误,常量必须声明并初始化 }