- 一个完整的类名需要包名与类名的组合,每个类都隶属于一个类包,只要保证同一类包中的类不同名,就可以有效地避免同名类冲突的情况
- 案例:
java.util.Data data=new java.util.Data(); java.sql.Data data=new java.sql.Data(123);
- 同一个包中的类相互访问时,可以不指定包名
- 同一个包中的类可以不必存放在同一个位置,只要将CLASSPATH分别指向它的位置就好
- 语法:
package 包名
- 包命名规则是全部使用小写字母
- 使用import关键字导入包
import com.lzw.*; //指定com.lzw包中的所有类在程序中都可以使用(包后面+“*”,表示可以使用包中全部类) import com.lzw.Math; //指定com.lzw包中的Math类在程序中可以使用
-
如果已经导入com.lzw.Math类,然后想使用java.lang包的Math类时,必须使用全名java.lang.Math
-
当使用import指定了一个包中所有类时,并不会指定这个包的子包的类,如果想要使用,需要再次对子包进行单独引用
-
使用import导入静态成员
import static 静态成员
- 案例
package com.lzw;
import static java.lang.Math.max;//导入静态成员方法
import static java.lang.System.out;//静态成员变量
public class importTest {
public static void main(String[] args) {
//在主方法中可以直接使用这些静态成员
out.println("1和4的较大值为:"+max(1,4));
}
}
1和4的较大值为:4final变量
- final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值(通常,final定义的变量为常量)
权限 final 类型 变量名=常量;
-
final关键字定义的变量必须在声明时对其进行赋值操作(除了可以修饰常量,还可以修饰对象引用)
-
一个既是static又是final的字段只占据一段不能改变的存储空间
-
案例:
package com.lzw;
import static java.lang.System.out;
import java.util.Random;
class Test{
int i=0;
}
public class FinalData {
static Random rand=new Random();
private final int VALUE_1=9;
private static final int VALUE_2=10;
private final Test test=new Test();
private Test test2=new Test();
private final int[] a= {1,2,3,4,5,6};
private final int i4=rand.nextInt(20);
private static final int i5=rand.nextInt(20);
public String toString() {
return i4+""+i5+"";
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
FinalData data=new FinalData();
//data.test=new Test();
//data.VALUE_2++;
data.test2=new Test();
for(int i=0;i
126
data2
186
126
-
被定义为final的常量定义时需要使用大写字母命名,并且中间使用下画线进行连接(这是Java的编码规则)
-
final的对象引用只能指向唯一一个对象,不可以再指向其它对象,但是对象本身的值却是可改变的,所以要想做到真正不可更改,可以声明为
权限类型 static final 类型 变量名称=值;
- 案例
package com.lzw;
import java.util.Random;
import static java.lang.System.out;
public class FinalStaticData {
private static Random rand=new Random();
private final int a1=rand.nextInt(10);
private static final int a2=rand.nextInt(10);
public static void main(String[] args) {
// TODO 自动生成的方法存根
FinalStaticData fdata=new FinalStaticData();
out.println("重新实例化对象调用a1的值:"+fdata.a1);
out.println("重新实例化对象调用a2的值:"+fdata.a2);
FinalStaticData fdata2=new FinalStaticData();
out.println("重新实例化对象调用a1的值:"+fdata2.a1);
out.println("重新实例化对象调用a2的值:"+fdata2.a2);
FinalStaticData fdata3=new FinalStaticData();
out.println("重新实例化对象调用a1的值:"+fdata3.a1);
out.println("重新实例化对象调用a2的值:"+fdata3.a2);
out.println("重新实例化对象调用a1的值:"+fdata3.a1);
out.println("重新实例化对象调用a2的值:"+fdata3.a2);
}
}
重新实例化对象调用a1的值:5
重新实例化对象调用a2的值:9
重新实例化对象调用a1的值:2
重新实例化对象调用a2的值:9
重新实例化对象调用a1的值:1
重新实例化对象调用a2的值:9
重新实例化对象调用a1的值:1
重新实例化对象调用a2的值:9
- 在Java中定义全局常量,通常使用public static final修饰,这样的常量只能在定义时被赋值
final方法
- 将方法定义为final类型,可以防止子类修改该类的定义于实现方式,而且final方法的执行效率要高于非final方法(一个private的方法隐式定义指定为final类型)
- 但是在父类中被定义为private final的方法似乎可以被子类覆盖,案例:
package com.lzw;
class Parents{
private final void doit() {
System.out.println("父类.doit()");
}
final void doit2() {
System.out.println("父类.doit2()");
}
public void doit3() {
System.out.println("父类.doit3()");
}
}
class Sub extends Parents{
public final void doit() {
System.out.println("子类.doit()");
}
public void doit3() {
System.out.println("父类.doit3()");
}
}
public class FinalMethod {
public static void main(String[] args) {
Sub s=new Sub();
s.doit();
Parents p=s;//向上转型操作
//p.doit();
p.doit2();
p.doit3();
}
}
子类.doit()
父类.doit2()
父类.doit3()
- 子类的doit方法覆盖父类的doit方法,必须满足一个对象向上转型为它的基本类型并调用相同方法这样一个条件
final类
-
定义为final的类不能被继承
-
语法:
final 类名{}
内部类
成员内部类
- 成员内部类简介
public class OuterClass{//外部类
private class InnerClass{}//内部类
}
- 在内部类中可以随意使用外部类的成员方法以及变量,那怕是private类型,但内部类的成员是不能被外部类使用的
- 内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上
- 案例:
public class OuterClass {
innerClass in=new innerClass();//在外部类实例化内部类对象引用
public void ouf() {
in.inf();//在外部类方法中调用内部类方法
}
class innerClass{
innerClass(){
}
public void inf() {
}
int y=0;//定义内部类成员变量
}
public innerClass doit() {
//y=4;//代码出错
in.y=4;
return new innerClass();//返回内部类引用
}
public static void main(String[] args) {
OuterClass out=new OuterClass();
//内部类的对象实例化操作必须在外部类或外部类的非静态方法中实现
OuterClass.innerClass in=out.doit();
OuterClass.innerClass in2=out.new innerClass();
}
}
- 如果在外部类和非静态方法之外实例化内部类对象,需要使用外部类
- 在实例化内部类对象时,不能在new之前使用外部类名称来实例化内部类对象,而是应该使用外部类对象
- 内部类会依赖于外部类对象,除非已经存在一个外部类对象,否则类中不会出现内部类对象
- 内部类向上转型为接口
interface OutInterface{
public void f();
}
public class InterfaceInner {
public static void main(String[] args) {
OuterClass2 out=new OuterClass2();
//调用doit方法,返回一个OutInterface接口
OutInterface outinter=out.doit();
outinter.f();
}
}
class OuterClass2{
private class InnerClass implements OutInterface{
InnerClass(String s){
System.out.println(s);
}
public void f() {
System.out.println("访问内部类中的f()方法");
}
}
public OutInterface doit() {//返回值类型为OuInterface接口
return new InnerClass("访问内部类构造方法");
}
}
-
如果某个类继承了外部类,由于内部的权限不可以向下转型为内部类InnerClass,同时也不能访问f()方法,但是却可以访问接口中的f()方法
-
非内部类不能被声明为private或protected访问类型
- 使用this关键字获取内部类与外部类的引用
- 如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字
public class TheSameName{
private int x;
private class Inner{
private int x=9;
public void doit(int x){
x++;//调用形参
this.x++;//内部类的x
TheSameName.this.x++;//外部类的x
}
}
}
- 在内存中所有对象均被放置在堆中,方法以及方法中的形参或局部变量放置在栈中
局部内部类
interface OutInterface2{}
class OuterClass3{
public OutInterface2 doit(final String x){
class InnerClass2 implements OutInterface2{//在方法中定义一个内部类
InnerClass2(String s){
s=x;
System.out.println(s);
}
}
return new InnerClass2("doit");
}
}
- 内部类InnerClass是doit()方法的一部分,并非OuterClass3的一部分,所以在方法外部不能访问该类,但是该类可以访问当前代码块的常量以及外部类的所有成员
- final String x:这是因为在方法中定义的局部变量相当于一个常量,它的生命周期超出方法的生命周期,由于该变量被设为final,所以不能在内部类中改变该局部变量的值
匿名内部类
- 在return语句中编写返回值为一个匿名内部类
class OuterClass4{
public OutInterface2 doit(){
return new OutInterface2(){//声明匿名内部类
private int i=0;
public int getValue(){
return i;
}
}
}
}
- 语法
return new A(){//A指类名
//内部类体
}
- 匿名内部类没有名称,所以默认使用默认构造方法来生成类对象
静态内部类
-
在非静态内部类中不可以声明静态成员
-
不可以使用外部类的非静态成员
-
特点:
- 如果创建静态内部类的对象,不需要其外部类的对象
- 不能从静态内部类的对象中访问非静态外部类的对象
-
案例:
public class StaticInnerClass{
int x=100;
static class Inner{
void doitInner(){//这行代码会报错,静态内部类不可以直接调用外部类的非静态成员变量
System.out.println("外部类"+x);//调用外部类的成员变量x
}
public static void main(String args[]){
System.out.println("a");
}
}
}
内部类的继承
- 案例:
public class OutputInnerClass extends ClassA.ClassB{
public OutputInnerClass(ClassA a){
a.super();
}
class ClassA{
class ClassB{
}
}
}
- 在某个类继承内部类时,必须硬性给予这个类一个带参数的构造方法,并且该方法的参数为需要继承内部类的外部类的引用,同时在构造方法体中使用a.super()语句,这样才为继承提供了必要的对象引用



