女神镇楼

类除了具有普通的特性之外,还有一些高级特性,比如包、内部类等。包在整个管理过程中起到非常积极的作用,使用包可以有效的管理繁杂的类文件,解决类重名的问题,当在类中配合包与权限修饰符使用时,可以控制其他人对类成员的访问。在java中一个更为有效的实现隐藏实现细节的技巧是使用内部类,通过使用内部类机制可以向上转型为被内部类实现的公共接口。由于在类中可以定义多个内部类,实现接口的方式也不止一个,只要将内部类中的方法设置为类最小范围的修饰符权限,就可以将内部类的实现细节有效的隐藏。

1、完整的类路径

在程序中使用两个不同的Date类的完整的类路径,可以使用如下代码:

java.util.Date date = newjava.util.Date();

java.sql.Date date2= new java.sql.Date(123);

在java中采用类包机制非常重要,类包不仅可以解决类名冲突的问题,还可以在开发庞大的应用程序时,帮助开发人员管理庞大的应用程序组件,方便软件复用。

在同一个包中,类相互访问时,可以不指定包名。

同一个包中的类,不必放在同一个位置,只要将CLASSPATH指向两个位置即可。

2、创建包

在IntelliJ IDEA中创建包:

在类的定义中,包名用法如下:

package 包名

在类中指定包名时,需要将package表达式放在程序的第一行,必须是文件的非注释代码第一行,使用package关键字为类指定包名后,包名会成为类名中的一部分,预示着这个类不许指定全名。例如,在使用位于com.lzw下的Dog.java类时,需要使用形如com.lzw.Dog的表达式。

3、导入包

(1)使用import关键字导入包

语法如下:

import com.lzw.*;

import com.lzw.Math;

使用import关键字时,可以指定类的完整描述,如果为了使用包中更多的类,可以在使用import关键字指定时在包的指定后加上*,表示可以在程序中使用包中的所有类。

4、使用import导入静态成员

语法如下:

import static 静态成员

代码示例:

packagecom.lzw;import static java.lang.Math.max; //导入静态成员方法

import static java.lang.System.out; //导入静态成员变量

public classImportTest {public static voidmain(String[] args) {//主方法中可以直接使用这些静态成员

out.println("1和4之间较大的值是:"+max(1,4));

}

}

使用import static 导入了java.lang.Math类中的静态方法max()和java.lang.System类中的out成员变量,就可以在程序中直接引用这些静态成员。

5、final变量

final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值,通常,final定义的变量为常量,例如:

final double PI = 3.14;

final关键字定义的变量在声明的时候,必须进行赋值操作,final除了可以修饰基本数据类型的常量,还可以修饰对象的引用。由于数组也可以看做是对象的引用,所以final可以修饰数组。一旦一个对象的引用被final修饰后,他只能恒定的指向一个对象,无法改变指向另一个对象。

代码示例:

packagecom.lzw;import staticjava.lang.System.out;importjava.util.Random;classTest{int i = 0;

}public classFinalData {static Random rand = newRandom();private final int VALUE_1 = 9; //声明一个final常量

private static final int VALUE_2 = 10;//声明一个final、static常量

private final Test test = new Test();//声明一个final引用

private Test test2 = new Test(); //声明一个不是final的引用

private final int[] a = {1,2,3,4,5,6}; //声明一个定义为final的数组

private final int i4 = rand.nextInt(20);private static final int i5 = rand.nextInt(20);publicString toString(){return i4 + " " + i5 + " ";

}

}

实例中,定义为final的常量定义时,需要使用大写字母命名,并且中间使用下划线链接,这是java的编码规则。同时,定义为final的数据,无论是常量、引用还是数组,在主函数中都不能被改变。

一个被定义为final的对象引用只能指向唯一一个对象,不可能将它再指向其他对象,但是一个对象本身的值却可以改变,那么使一个常量真正做到不可更改,可以将常量声明为static final 。

6、final方法

定义的final方法不能被重写,方法定义为final类型,可以防止子类修改该类的定义和实现方式,同时定义为final的方法执行效率要高于非final的方法。在权限修饰符中,private修饰符,如果一个父类的某个方法被定义为private修饰符,子类将无法访问这个方法,自然也就无法覆盖该方法,所以定义一个private方法隐式的被指定为final类型。

但是在父类中被定义的private final类型似乎可以被子类覆盖

代码示例:

classParent {private final voiddoit(){

System.out.println("父类的doit方法。");

}final voiddoit2(){

System.out.println("父类的doit2方法");

}public voiddoit3(){

System.out.println("父类的doit3方法。");

}

}

class Sub extendsParent {public final voiddoit(){

System.out.println("子类中的都doit方法");

}/*final void doit2(){ // final方法不能被覆盖

System.out.println("子类企图覆盖doit2方法,但是编辑器不允许");

}*/

public voiddoit3(){

System.out.println("子类的doit3方法");

}

}

public classFInalMrthod {public static voidmain(String[] args) {

Sub s= new Sub(); //实例化子类

s.doit();//调用doit()方法

Parent p = s; //执行向上转型操作//p.doit();//会报错,不能执行private方法

p.doit2();

p.doit3();

}

}

示例分析:

final方法不能被覆盖,doit2()方法不能再子类中被重写,但是在父类中定义了一个private final 的doit()方法,在子类中也定义了一个doit()方法,表面上看子类的doit()方法覆盖了父类的doit()方法,但是覆盖必须满足一个对象向上转型为他的基本类型,并调用相同方法这样一个条件。在主方法中"Parent P = s"是向上转型的操作,对象p只能调用正常覆盖的doit3方法,却不能调用doit()方法,可见子类中的doit()不是正常的覆盖,而是生成了一个新的方法。

7、final类

final类不能被继承,如果希望一个类不允许被任何类继承,不允许其他人对这个类进行任何修改,这个类可以设置为final形式。

语法如下:

final 类名{}

如果类设置为final形式,则类中所有的方法都被隐式的设置为final形式,但是final中的成员变量可以设置为final或者非final形式。

代码示例:

final classFianlClass {int a = 3;voiddoit(){

}public static voidmain(String[] args) {

FinalClass f= newFinalClass();

f.a++;

System.out.println(f.a);

}

}

8、成员内部类

(1)简介

语法:

public class OuterClass { //外部类

private class innerClass{ //内部类

}

}

内部类可以随意使用外部类定义的成员变量和成员方法,即使类成员被定义为private方法。内部类的实例一定要绑定外部类的实例上,如果外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。

//>> TODO 成员内部类,是在类中直接定义类//>> TODO 成员内部类,不可以包含任何静态的成分,比如静态方法,静态变量,静态内部类。否则会造成内外部类初始化问题。//>> TODO 成员内部类,可以有访问控制符。成员内部类和成员方法,成员变量一样,都是类的组成部分

public classCPU {//>> TODO 可以有final static的基本数据类型变量

final static int abc = 999;privateString producer;publicCPU(String producer) {this.producer =producer;

}public doublegetSpeed() {//>> TODO 成员内部类,代码和这个类本身的访问权限一样,可以访问外部(Phone)的private属性//>> TODO 成员内部类中有一个外部类的引用,其访问外部类的对象的成员属性就是使用这个引用,完整写法是:类名.this.属性/方法

return Phone.this.speed;

}publicString getProducer() {returnproducer;

}public voidsetProducer(String producer) {this.producer =producer;

}

@OverridepublicString toString() {return "CPU{" +

"speed=" + getSpeed() +

", producer='" + producer + '\'' +

'}';

}//>> TODO 成员内部类,里面可以有任意合法的类的组成部分,包括成员内部类,但是不可以有静态内部类//public class ABC{//public void test(){//

//}//}

}

代码示例:

public class OuterClass { //外部类

innerClass in = new innerClass(); //在外部类实例化内部类对象引用

public voidouf(){

in.inf();//在外部类方法中调用内部类方法

}private class innerClass{ //内部类

innerClass(){//内部类的构造方法

}public voidinf(){//内部类的成员方法

}int y = 0; //定义内部类成员变量

}publicinnerClass doit(){//外部类方法,返回值为内部类引用

in.y = 4;return new innerClass(); //返回内部类引用

}public static voidmain(String[] args) {

OuterClass out= newOuterClass();//内部类对象实例化操作必须在外部类或者外部类的非静态方法中实现

OuterClass.innerClass in =out.doit();

OuterClass.innerClass in2= out.newinnerClass();

}

}

示例分析:

外部类创建内部类实例,与其他类创建对象引用时相同。内部类可以访问他的外部类成员,但是内部类成员只能在内部类范围内是可知的,不能呗被外部类使用。在实例化内部类对象时,不能再new操作符之前使用外部类名称实例化内部类对象,而是应该使用外部类对象来创建其内部类对象。

(2)内部类向上转型为接口

如果讲一个权限修饰符为private的内部类向上转型为其父类对象,或者直接向上转型为一个接口,在程序中就可以完全隐藏内部类的实现过程。可以在外部提供一个接口,在接口中声明一个方法。如果在实现该接口的内部类中实现了给接口的方法,就可以定义多个内部类以不同的方式实现接口中的同一个方法,而一般的类中是不能多次实现接口中同一个方法的,这个技巧经常被应用在Swing编程中,可以在一个类中做出多个不同的响应事件。

代码示例:

packagecom.lzw;public interfaceOutInterFace {public voidf();

}

importcom.lzw.OutInterFace;public classInterfaceInner {public static voidmain(String[] args) {

OutClass2 out= new OutClass2(); //实例化一个OutClass2对象//调用doit方法,返回一个OutInterface接口

OutInterFace outInte =out.doit();

outInte.f();

}

}

importcom.lzw.OutInterFace;public classOutClass2 {//定义一个内部类实现OutInterFace接口

private class InnerClass implementsOutInterFace {

InnerClass(String s){//内部类构造方法

System.out.println(s);

}

@Overridepublic void f() { //实现接口中的f()方法

System.out.println("访问内部类中的f()方法");

}

}public OutInterFace doit(){ //定义一个方法,返回值类型为OutinterFace接口

return new InnerClass("访问内部类构造方法");

}

}

示例分析:

OutClass2类中定义了一个权限修饰符为private的内部类,这个内部类实现了OutInterFace接口,然后修改了doit()方法,使得该方法返回一个OutInterFace接口。由于内部类InterClass的修饰符为private,所以只能被OutClass2的类访问,其他的类可以访问doit()方法。由于该方法返回的是一个外部接口类型,这个接口可以作为外部使用的接口。他包含一个f()方法,在继承此接口的内部类中实现了此方法,如果某个类继承了外部类,由于内部的权限不可以向下转型为内部类InterClass,同时不能方位f()方法,但是可以访问接口中的f()方法。例如InterFaceInner类中的最后一条语句,接口引用调用f()方法,从执行结果可以看出,这条语句执行的是内部类中的f()方法,很好的对继承该类的子类隐藏了实现细节,仅为编写子类的人留下了一个接口和一个外部类,同时也可以调用f()方法,但f()方法的实现过程却很好的隐藏了,这就是内部类最基本的用途。

(3)使用this关键字获取内部类与外部类的引

如果外部类定义的成员变量与内部类中的成员变量名称相同,可以使用this关键字

代码示例:

public classTheSameName {private intx ;private classInner{private int x = 8;public void doit(intx){

x++; //调用的是形参 x

this.x++; //调用的是内部类的变量x

TheSameName.this.x++; //调用的是外部类的变量x

}

}

}

示例分析:

在内部类中使用this,x可以调用内部类的成员变量x,使用ThsSameName.this.x语句可以调用外部类成员变量x,即:

外部类名称.this.变量名   =====可获取外部类引用

9、局部内部类

内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或者任意作用域中都可以定义内部类。

//>> TODO 接口也可以定义为静态内部接口,但是一般不这么做。接口的目的是为了让更多人实现,所以一般会是单独一个文件作为公共接口

public static interfaceUnitSpec {public doublegetNumSpec();publicString getProducer();

}publicPhone(

String name, String id,int count, double soldPrice, doublepurchasePrice,double screenSize, double cpuHZ, int memoryG, intstorageG, String brand, String os

) {double localCPUHZ =cpuHZ;//localCPUHZ = Math.random();//>> TODO 局部内部类,是在类中直接定义类//>> TODO 局部内部类,不可以包含任何静态的成分,比如静态方法,静态变量,静态内部类。否则会造成内外部类初始化问题。//>> TODO 局部内部类,不可以有访问控制符。局部内部类和成员方法,成员变量一样,都是类的组成部分

class CPU implementsUnitSpec {//>> TODO 可以有final static的基本数据类型变量

final static int abc = 999;privateString producer;publicCPU(String producer) {this.producer =producer;

}public doublegetNumSpec() {//>> TODO 局部内部类,代码和这个类本身的访问权限一样,可以访问外部(Phone)的private属性//>> TODO 局部内部类中有一个外部类的引用//>> TODO 局部内部类访问外部类的对象的成员属性的完整写法如下,类名.this.属性/方法//>> TODO 以上都和成员内部类一样。除此之外,局部内部类还可以访问参数和局部变量,但是它俩必须是实际final的//仅做访问数据的演示,没有实际意义

return Math.max(Phone.this.speed, Math.max(cpuHZ, localCPUHZ));

}publicString getProducer() {returnproducer;

}public voidsetProducer(String producer) {this.producer =producer;

}

@OverridepublicString toString() {return "CPU{" +

"speed=" + getNumSpec() +

", producer='" + producer + '\'' +

'}';

}//>> TODO 局部内部类,就好像局部变量一样,方法内部的东西出了代码就不可被访问,//>> TODO 所以可以再定义类,但是不能有访问控制符,也不能是static,就好像成员变量没有访问控制符没有static一样//>> TODO 但是可以有final。记忆要点:和局部变量一样//final class ABC {//public void test() {//

//}//}

}class Memory implementsUnitSpec {privateString producer;publicMemory(String producer) {this.producer =producer;

}

@Overridepublic doublegetNumSpec() {returnmemoryG;

}publicString getProducer() {returnproducer;

}publicString toString() {return "Memory{" +

"storage=" + getNumSpec() +

", producer='" + producer + '\'' +

'}';

}

}this.screenSize =screenSize;//>> TODO 可以像平常的类一样使用局部内部类

this.speed =cpuHZ;this.cpu = new CPU("Default");this.memoryG = new Memory("Default");this.storageG =storageG;this.brand =brand;this.os =os;this.setName(name);this.setId(id);this.setCount(count);this.setSoldPrice(soldPrice);this.setPurchasePrice(purchasePrice);

}

View Code

代码示例:

packagecom.lzw;public interfaceOutInterFace2 {

}

importcom.lzw.OutInterFace2;public classOutClass3 {public OutInterFace2 doit(finalString x){//doit()方法的参数为final类型//在doit()方法中定义一个内部类

class InnerClass2 implementsOutInterFace2{

InnerClass2(String s ){

s=x;

System.out.println(s);

}

}return new InnerClass2("doit");

}

}

示例分析:

内部类定义在了方法doit()内部,内部类InterClass2是doit()方法的一部分,并非是OutClass3类的一部分,所以在doit()方法的外部不能访问该内部类,但是内部类可以访问该代码块的常量以及此外部类的所有成员。

doit()方法的参数设置为final类型,如果需要在方法体中使用局部变量,该局部变量需要设置为final类型,在方法中定义的内部类只能访问方法中final类型的局部变量,这是因为方法中定义的局部变量相当于一个常量,他的生命周期超出了方法运行的生命周期,由于该局部变量被设置为final,所以不能再内部类中改变局部变量的值。

10、匿名内部类

匿名类的所有代码需要在大括号之间编写,语法如下:

return newA(){//内部类体

};

代码示例:

importcom.lzw.OutInterFace2;public classOuterClass4 {public OutInterFace2 doit(){//定义doit()方法

return newOutInterFace2() {private int i = 0;public intgetValue(){returni;

}

}

}

}

示例分析:

在doit()方法内部首先返回一个OutInterFace2的引用,然后在return语句中插入一个定义内部类的代码,由于这个类没有名称,所以将该内部类成为匿名内部类。实际上这种内部类的作用就是创建一个实现于OutInterFace2接口的匿名类的对象。

11、静态内部类

在内部类前添加static修饰符,这个内部类就变成静态内部类了。一个静态内部类中可以声明static成员,但是非静态内部类中不可以声明静态成员。静态内部类一个最大的特点:就是不可以使用外部类的非静态成员,所以静态内部类在程序开发中比较少见。

//>> TODO 静态内部类,是在类中使用static修饰的类//>> TODO 静态内部类,可以有访问控制符。静态内部类和静态方法,静态变量一样,都是类的静态组成部分//>> TODO 静态内部类也是类,在继承,实现接口方面,都是一样的。以后我们讲的类,不特殊说明,在这方面都是一样的

public static classCPU {private doublespeed;privateString producer;public CPU(doublespeed, String producer) {this.speed =speed;this.producer =producer;

}public doublegetSpeed() {//>> TODO 静态内部类,代码和这个类本身的访问权限一样,可以访问外部(Phone)的private属性//>> TODO 注意,这并不少说它可以访问private变量,//>> TODO 静态内部类是静态的,就好像静态方法一样,没有this自引用,可以通过引用访问Phone对象的private属性//仅作演示访问性,不具有实际意义

Phone phone = null;

phone.memoryG= 99;returnspeed;

}public void setSpeed(doublespeed) {this.speed =speed;

}publicString getProducer() {returnproducer;

}public voidsetProducer(String producer) {this.producer =producer;

}

@OverridepublicString toString() {return "CPU{" +

"speed=" + speed +

", producer='" + producer + '\'' +

'}';

}//>> TODO 静态内部类,里面可以有任意合法的类的组成部分,包括静态内部类//public static class ABC{//

//}

}public voidaccessStaticClass(){//>> TODO 同样,外部类也可以访问静态内部类(CPU)的private属性//仅作演示访问性,不具有实际意义

this.cpu.producer = "";

}

12、内部类的继承

内部类和其他普通类一样可以被继承,但继承内部类比继承普通类要复杂,需要设置专门的语法完成

public class OutputInnerClass extendsClassA.ClassB {publicOutputInnerClass(ClassA a){

a.super();

}

}classClassA{classClassB{}

}

在某个类继承内部类时,必须硬性的给予这个类一个带参数的构造方法,并且该构造方法的参数为需要继承内部类的外部类引用,同时在构造方法体中使用s.super()语句,这样才能为继承提供了必要的对象引用。

fianl属性 java_java基础-类的高级属性(包、final、内部类)相关推荐

  1. MobX基础 ----- 类的静态属性和装饰器

    当我们使用MobX的时候,首先要声明一个store, 用来保存状态,它的最基本的语法 如下: class Todo {@observable title = "";@observa ...

  2. python类属性初始化_Python类定义、属性、初始化和析构

    类的定义,属性和方法概念 方法中self的作用和意义 初始化( __init__ ) 和 析构方法( __del__ ) 类的定义 class 类名 实例 实例名 = 类名() 一个"实例& ...

  3. java 遍历类属性_Java 遍历类中的属性

    public static void testReflect(Object model) throwsNoSuchMethodException, IllegalAccessException, Il ...

  4. 8.类定义、属性、初始化和析构

            类定义        类 是一个独立存放变量(属性/方法)的空间 封装: 类可以把各种对象组织在一起,作为类的属性,通过 . (点)运算符来调用类中封装好的对象 属性: 变量在类中称为 ...

  5. 【python进阶】类的__slots__属性

    python作为一门动态语言,可以在对象创建后动态的添加属性和方法. 示例1:动态添加属性 class Dog(object):def __init__(self, name, age):self.n ...

  6. python基础和第三方库 笔记(python基础完结包括高级用法,第三方库持续更新中...)

    python基础 注:本笔记面向有一定基础的人 本笔记是本人快速复习python过程中记录的,不适合零基础的人学习python的主工具,可以作为辅工具,本笔记记录了入门阶段常用操作,如有错误的地方,希 ...

  7. 内省、JavaBean、PropertyDescriptor类、Introspector类、BeanUtils工具包、注解、Rentention、Target、注解的基本属性和高级属性...

    内省.JavaBean.PropertyDescriptor类.Introspector类.BeanUtils工具包.注解.Rentention.Target.注解的基本属性和高级属性 本文转载自:h ...

  8. 1023day5:class类属性方法、每次执行类属性+1、内建模块、时间装饰器wrapper、面向对象__slots__方法:限制类的属性等基础知识、正则表达式基础知识、多态鸭子类型

    文章目录 一.类class 1.Python类class 属性 方法 2.类的构造方法__init__() 3.每次执行一次类的属性+1 二.模块 1.内建模块 2.第三方模块 3.定义自己的模块 三 ...

  9. 类属性的特征java_java定义类、属性、方法

    Java是面向对象的程序设计语言,Java语言提供了定义类.定义属性.方法等最基本的功能.类可被认为是一种自定义的数据类型,可以使用类来定义变量,所有使用类定义的变量都是引用变量,它们将会引用到类的对 ...

最新文章

  1. linux arm中断跑马灯,S3C2410 MDK实验---ARM汇编语言实现跑马灯
  2. CNN、RNN、GAN都是什么?终于有人讲明白了
  3. 突破屏蔽限制,自己的网站使劲弹新IE窗口
  4. mysql免安装版鞋子_MySQL创建用户及授权
  5. SpringMVC获取参数的几种方式
  6. SAP CRM Pricing Procedure中的Doc和Customer Procedure在哪里维护
  7. [CTSC2017]吉夫特(Lucas定理,DP)
  8. python中paste函数_PIL图像处理模块paste方法简单使用详解
  9. 树莓派安装python3.8_在树莓派(Raspberry Pi)上编译安装更新版本的Python
  10. 干货:完全基于情感词典的文本情感分析
  11. Win7系统能用一键装机的方式安装win10吗?
  12. svn 分支上新增文件合并发生冲突_windows 下svn 创建分支 合并分支 冲突
  13. android 360 root权限获取root权限,安卓手机如何Root 使用360手机助手获取root权限图为教程...
  14. 【云和恩墨业务介绍】之数据库性能优化服务
  15. java ftp 下载 0k_Ftp下载文件大小为0 KB
  16. 1388. 3n 块披萨
  17. html5border设置彩色,css中border颜色不同怎么设置?
  18. 高级弥散模型:单指数、IVIM、DKI、SEM、FROC、CTRW
  19. 100款现代科技感的英文字体打包分享
  20. Nofollow标签是什么,使用Nofollow标签有哪些好处?

热门文章

  1. 原创 | 我说我了解集合类,面试官竟然问我为啥HashMap的负载因子不设置成1!?...
  2. DDD+分布式+负载均衡+服务治理已撸!微服务架构不就这点事?
  3. 低代码平台真的能拯救程序员的996吗?
  4. 微信公众帐号开发教程第17篇-应用实例之智能翻译
  5. 微服务技术栈:常见注册中心组件,对比分析
  6. 大数据之HBase部署
  7. Linq语言集成查询
  8. Linux系列之fdisk 分区挂盘
  9. 荷兰籍空乘服务中国春运:对春节有着别样的感受
  10. Oracle的sql开发之包技术实战