zoukankan      html  css  js  c++  java
  • 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类. 

    我们如果不使用关键字 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)

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

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

    package 关键字

     package 包名.

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

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

    例如:

      

      4.导入包

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

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

    import关键字.

    语法:

      import 包名.通配符. 

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

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

      5.Import的高级用法

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

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

    二丶Final关键字的作用

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

    变量:

        1.修饰变量

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

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

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

      

      空白final成员变量初始化

      .2.final 修饰对象

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

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

    如下.:

      

       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);
        }

    输出结果

    可以看出.我们对象中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.成员变量;  这样使用的就是外部类的成员

  • 相关阅读:
    【转】HTTP协议/IIS 原理及ASP.NET运行机制浅析【图解】
    【转】windows server 2012 R2搭建IIS服务器
    【转】新建网站(CodeFile)与新建Web应用(Codebehind)的区别
    微信小程序前端坑
    开题报告
    十大API网站
    animate使用方法
    简易音乐小程序
    如何在app.js 和其他页面中更改globalData的值
    qq音乐解析API
  • 原文地址:https://www.cnblogs.com/iBinary/p/9798529.html
Copyright © 2011-2022 走看看