Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

          Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

一丶Java中包的机制

  首先包其实就是个文件夹.作用就是管理类. Java中每次定义一个类的时候.通过Java编译之后.都会生成一个扩展名为.class的文件.但是当这个程序规模逐渐庞大的时候.就很容易发生类名名称冲突的现象. 那么JDK API中. 提供了成千上万的具有各种功能的类.有效的管理就是通过类包来管理.

    1.类名冲突

      首先我们Java中可能定义一个A类.但是因为业务需要.还需要一个A类.名称一样,可能功能不一样.那么名字就会冲突.而Java编译器不允许存在同名的类文件.解决方法

就是放在不同的文件夹中(包中)

    2.完整的类路径

      在以前我们使用Math类.eclipse会自动引入一个包.关键字就是 import 包. 我们当时也不注意.反正能编写程序即可. 其实Math类.完整的路径是 Java.lang.math;

java.lang 是包的名称,可以理解为是文件夹. 后面的math是类名. 我们使用 import java.lang.Math 代表的意思就是 使用这个文件夹下指定的Math类.

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

我们如果不使用关键字 import引入包. 那么就要使用完整的类名 例如: java.lang.Math ma = new java.lang.Math();

注意:

    1.同一个包中的类互相访问的时候,可以不指定报名.

    2.同一个包中的类可以不用放在一个磁盘.什么意思. java.lang 是报名. 我们可以在D盘创建一个 java.lang  E盘我们也创建一个java.lang 此时我们只需要CLASSPATH指向这两个包就行.包他认为就是一个.都属于java.lang包. 这跟文件夹不太一样.

  3.创建包.

我们可以使用Eclipse创建一个包. 新建->包. (new -> packet)

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

填写文件夹. 以及包名称即可.

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

创建完毕之后就有一个包了.在我们的项目中.

package 关键字

package 包名.

我们在类中指定包名的时候.需要将package表达是放置在程序的第一行. 他必须是文件中第一行.并且是非注释代码. 如果指定了包名称.那么代表这个类的完整路径就是

包名.类名称. 例如 com.aaa是我们的包. 在下面定义了一个类. Dog()  那么Dog类的完整路径就是  com.aaa.Dog();

例如:

  Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

  4.导入包

我们上边虽然定义了包.但是使用的时候我们必须指定完全的类名去创建对象.例如如下:

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

我们不能每次new对象的时候都要加上包的名称.所以我们可以使用关键字.导入包.这样使用的时候直接给定类名即可.

import关键字.

语法:

  import 包名.通配符.

例如: import com.xxx.Math  也可以 import com.xxx.*;  表示导入这个包中所有的类.

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

注意:如果你有两个相同类.你要使用那个类.就要加上完整的类名去使用. 这个便于区分. java中的类包.类似于C++的命名空间.都是解决冲突问题.

  5.Import的高级用法

Import不光可以导入类包.也可以导入静态变量.这个是 J2SE 5.0以上才支持的.

关键字:import static 包名+静态成员变量 代码如下.

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

二丶Final关键字的作用

  Final关键字是常量定义关键字. 他可以修饰类 方法. 以及变量跟引用.

变量:

    1.修饰变量

  1.修饰变量. 变量不可以修改.成了一个常量. 例如 final double PI = 3.14; 此时PI我们只可以访问而不能修改了.在修饰变量的时候应该直接进行初始化.

   C++ 则是在类外面加上类域进行初始化 const int 类名::变量 = 初始化的值;

  在Java类中如果只定义了final成员变量.那么初始化可以在构造函数中进行初始化.

  Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

  空白final成员变量初始化

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

  .2.final 修饰对象

    final修饰对象.则对象只能指定唯一的一个对象.且不能修改.

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

  如果修饰数组.则数组里面的值可以修改.但是数组对象不能指向别的数组了.

如下.:

  Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

   3.final与static的使用

    final 修饰的变量.初始化的时候可以使用随机数进行初始化.这样常量的值就是可以改变的.但是如果加上Static关键字.那么意思就是其内存区域是恒定不变的.所以值不会被改变了.

代码如下:

  

public class Cat {

    private static Random r = new Random();

    public final int a = r.nextInt(10);      //常量a
public final static int b = r.nextInt(10); //静态区域的常量b
public Cat() { }
public void eat() {
System.out.println("猫在吃饭");
};
}

使用

  

    public static void main(String[] args) {
Cat c = new Cat();
out.print("a = " + c.a);
out.println(" b = " + c.b); Cat b = new Cat(); out.print("a = " + b.a);
out.print(" b = " + b.b);
}

输出结果

Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

可以看出.我们对象中final修饰的a也就是变量a随机数可以进行改变的.但是b因为是static所以不能被改变了.

在Java中 定义全局变量一般都是用 public static final 修饰. 这样修饰的只能在定义的时候并且初始化.可以这样使用.

方法:

  

   1.父类方法private + final修饰

以前我们知道.当父类中的方法 使用private修饰的时候.则子类继承父类的时候.则不能覆盖(重写)

而将方法使用final修饰的话.可以防止子类修改该类的定义与实现方式. 所以父类中使用private修饰的时候.

方法自然地加上了默认修饰符 final. 因为final修饰的方法效率远高于非final的方法.

注意下方代码:

父类:

  

 public   class  Anmail {

    final private void eat1() {
System.out.println("父类吃1");
}
final public void eat2() {
System.out.println("父类吃2");
}
}

子类:

  

public class Dog extends Anmail implements IAnmail{

    public final void eat1() {
System.out.println("子类吃1");
} public final void eat2() {
System.out.println("子类吃2");
} @Override
public void Play() {
// TODO 自动生成的方法存根 } }

我们可以看到.我们子类竟然可以 "覆盖父类方法"  并且权限已经改为public 请注意.这个并不是覆盖.而是子类的一个新的方法.

跟父类的方法不一样.也没有进行重写.

final类

  final修饰的类则不能被继承了.

语法:

  final class 类名{}

三丶类的高级特性.内部类.

  在java中.类中可以使用内部类.意思就是在一个类中还可以定义一个类.

1.成员内部类

   成员内部类就是定义一个成员.这个成员就是一个内部类.

例如:

  

public class A{
private class B{
.....内部类代码.
}
}

其中 A是外部类. B是内部类.

B内部类可以随意使用外部类的成员变量以及成员方法. 不管这些类是否被修饰为private.

在外部类可以new 内部类.使用内部类.

例如:

public class A{
class B{
....
}
B b = new B(); 使用内部类
}

内部类的使用:

  内部类的实例化跟外部类一样.只不过你是内部类我们跟Java类包一样. 加上外部类名即可. 但是在new的时候有区别.

new的时候要在外部类中提供一个方法.这个方法专门是返回内部类的实例化对象.

public class Cat {

    public class Cat1{
public int m_hande;
public void eat() {
System.out.println("内部类吃东西");
}
}
  Cat1 retInstance(){ //专门提供一个方法.进行返回成员内部类的实例化对象.
return new Cat1();
}
}

使用:

  

public static void main(String[] args) {
Cat c = new Cat(); //创建外部类对象
Cat.Cat1 b = c.retInstance(); //外部类的方法返回内部类实例 b.eat();
}

或者使用以下方法.

public static void main(String[] args) {
Cat c = new Cat();
Cat.Cat1 b = c.new Cat1();//使用new b.eat();
}

这里注意的就是一定要创建出外部类对象才可以使用内部类.

1.外部类方法返回内部类实例.

2.外部类中直接当成员使用.使用new的方法.new一个. 因为Cat1我们可以看成是一个成员变量.只不过是一个特殊的成员变量.

成员内部类的高级用法

  成员内部类可以向上转型为父类. 成员内部类可以实现一个接口.对外隐藏其实现方法.

例如如下;
定义接口:

  

public interface IAnmail {

    public abstract void Play(); //定义一个抽象方法
}

父类跟成员内部类

public class Cat {

    public class Cat1 implements IAnmail {

        @Override
public void Play() {
// TODO 自动生成的方法存根
System.out.println("内部类玩耍");
} //实现IAnmail方法 }
public Cat1 retInstance(){ //专门提供一个方法.进行返回成员内部类的实例化对象.
return new Cat1();
}
}

可以看到.内部类Cat 实现了接口IAnmail. 并且外部类返回了内部类的实例化对象.

使用:

public static void main(String[] args) {
Cat c = new Cat();
IAnmail b = c.retInstance();//注意此行代码
b.Play(); }

注意第二行代码:

.返回的是内部类实例化对象.使用接口接受.意思就是说向上转型为了父对象.父对象直接使用play方法. 这样可以隐藏内部类的实现细节. 其实本质区别没有变.还是类跟类的关系.
只不过是内部类而已.
这样做的好处是什么: 好处就是一般的类.不能多次实现接口中的方法. 而我们的内部类可以.我们可以写上几个内部类.去实现接口.并且多次实现其方法. 因为向上转型.会触发多态.
所以一个类中可以有不同的事件产生.这个一般用于窗口设计中.Android中好像也是这样.还没接触安卓.不过按照书上所写.应该可以同时监听不同的事件.

  this关键字用于内部类跟外部类

我们以前说过.this可以访问构造.也可以区分成员变量与局部变量的命名冲突. 但是此时我们的内部类中有成员的变量.跟外部类中的成员变量相同怎么办.

所以我们必须进行区别.

用一下代码进行区别.

public class Cat {
int x = 0; //外部类的X
public class Cat1 {
int x = 1; //内部类的x
public void eat(int x) {//方法中的形参x
x ++ ; //操作的是方法中的形参x
this.x ++; //操作的是内部类的x
Cat.this.x++;//前边加上外部类名则是操作的外部类的成员变量x }
public class cat2{
int x;
public void eat(int x) {
x++;
this.x++;
Cat1.this.x ++;
Cat.Cat1.this.x++;
}
} }
public Cat1 retInstance(){ //专门提供一个方法.进行返回成员内部类的实例化对象.
return new Cat1();
}
}

首先总结来说.

this用于当前类.那么则是区分的本类的成员变量与形参.

如果this前边加上父类名. 则是操作的父类的成员变量.

下面我们写了内部类的内部类. 使用this的时候就是 都是加外部类名. 只不过类名不一样而已. 依次类推.

2.方法内部类 /局部内部类.

  方法内部类就是说.可以定一个方法.这个方法中可以定义一个类去使用.

因为他是属于一个方法的.是一个方法中的类.所以外部类不可以访问局部内部类. 但是内部类可以访问当前代码块的常量以及外部类的所有成员.

代码如下:

  

public class Cat {
int x = 0; //外部类的X public IAnmail retInstance(){ //专门提供一个方法.进行返回成员内部类的实例化对象. class Cat1 implements IAnmail{ public void Play() {
// TODO 自动生成的方法存根
System.out.println("内部进行玩耍");
} }
return new Cat1(); //返回实例化对象.但是需要用父类进行接收.因为外部没有此类对象
}
}

使用:

  

public static void main(String[] args) {
Cat c = new Cat();
IAnmail b = c.retInstance();
b.Play(); }

局部内部类很简单.就是方法中定义一个类.而返回的时候可以返回这个类的实例对象.使用父类接受.可以向上转型.

3.匿名内部类.

  上面所说的局部内部类.返回的时候是自己new了一个对象进行返回.且外面进行接受了. 我们还可以使用return的时候.字节返回.

就不用类定义了.

代码如下:

  

public class Cat {
int x = 0; //外部类的X public IAnmail retInstance(){ return new IAnmail() { @Override
public void Play() {
// TODO 自动生成的方法存根
System.out.println("匿名内部类");
} };
}
}

匿名内部类就是跟return语句进行结合了. 还是在方法内部.

以前我们返回的是 new Cat1(); 现在我们知道返回值是一个接口.我们可以直接返回一个接口类.

其实这个类的作用就是返回一个实现接口的对象而已.

语 法: new A () {

....

}

A可以是一个接口. 父类. 向上转型类都可以.

4.静态内部类.

  在内部类前边添加修饰符static.那么就是静态内部类. 静态内部类中可以声明static成员.但是不是静态内部类不可以声明静态成员.

特点: 不可以使用外部类的非静态成员. 所以静态内部类开发中很少见.

可以理解为静态内部类加了很多现实.

1.如果创建静态内部类的对象.不需要其他外部类的对象.

2.不能从静态内部类的对象中访问非静态外部类的对象.

5.内部类的继承

  如果一个类.想要继承一个内部类.

比如有一个A类.一个B类. B类中有内部类C类.

我们的A类想要继承B中的C类.

那么A类就要提供一个带参构造. 参数是类 B.

且构造参数中需要加上a.super():才可以.

代码如下.

 public   class  AnmailB {

     public class AnmailC{

     }
}

使用一个类继承AnmailC

public class Cat  extends AnmailB.AnmailC{
public Cat( AnmailB b) {
b.super();
} }

四丶总结

    1).Java中的类包

      package 包名  用来定义一个包

      import  包名.类名 导入一个包中的某个类. 可以直接使用这个类new对象了.而不用加上完整包路径

    2).java中的final变量

      final 修饰变量 变量变量变成常量.且不能修改

      final 修饰引用. 引用只能指向一个对象.不能更改指向. 但是引用里面的成员变量的值可以修改.

      final 修饰数组. 数组里面的值可以改变.地址不能改变了.意思就是不能更改指向了.

      final 跟 static一起使用 final 修饰常量.可以被随机数修改值.也就是初始化的时候. 但是加上static则内存是一块不能改变的. 也就是说值被赋值之后.内存里面的值不会在进行改变了.

      final 修饰方法. 则方法不能被继承跟重写. private权限.默认加了final关键字.

    3).java中的内部类.

    1.成员内部类.

      成员内部类就是一个成员.  使用的时候外部类提供方法.用来返回内部类的实例化对象.

       A.B  a = A.retInstance(); 或者 A.B a = A.new B();

      成员内部类可以实现接口. 返回的时候可以使用父类接受. 向上转型.隐藏实现细节.

      接口 A = A.new B();  内部类可以实现多个接口中方法.用来监听不同的事件.

    2.局部内部类,方法内部类.

      定义一个方法.方法中定义一个类.返回的时候可以返回这个类的实例化对象. 返回值可以是 实现的接口.或者父类.向上转型.

    3.匿名内部类. 

      匿名内部类直接返回一个实现接口的对象即可.

      例如  return new 接口(){  xxx代码};

    4.静态内部类.

      静态内部类就是给类加了限制.不能访问外部类的非静态成员. 内部类中只能定义静态成员.

    4).this关键字用于内部类

      this关键字用于类内部可以区分类的成员变量跟形参区别.

      如果想使用外部类.则要加上外部类的类名才可以  外部类名.this.成员变量;  这样使用的就是外部类的成员

上一篇:Java语言基础(五)


下一篇:第三章:Python高级编程-深入类和对象