Java基础--------常用类 & 内部类

目录

一. 常用类

1.1 Java中的包装类

1.2 Date 和 SimpleDateFormat类

1.3 Calendar 类

1.4  Math 类

1.5 Runtime类

1.6  Random类

1.7  StringUtils工具类

二. 内部类

2.1内部类相关概念

2.1.1 内部类定义

2.1.2 内部类基础

2.3 成员内部类

2.4 局部内部类

2.5 匿名内部类

2.6  静态内部类


一. 常用类

1.1 Java中的包装类

  对基本数据类型都非常熟悉,例如 int、float、double、boolean、char 等。基本数据类型是不具备对象的特性的,比如基本类型不能调用方法、功能简单。为了让基本数据类型也具备对象的特性, Java 为每个基本数据类型都提供了一个包装类这样我们就可以像操作对象那样来操作基本数据类型。 

基本类型和包装类之间的对应关系:

包装类主要提供了两大类方法:
1. 将本类型和其他基本类型进行转换的方法
2. 将字符串和本类型及包装类互相转换的方法

Integer 包装类为例,来看下包装类的特性。

Integer 包装类的构造方法:

如下代码所示:

public class First {
    public static void main(String []args){
        int a=2;//定义int类型变量
        Integer m=new Integer(5);//定义Integer包装类对象
        Integer n=new Integer("8");//定义Integer包装类对象
        System.out.println("a="+a);
        System.out.println("m="+m);
        System.out.println("n="+n);
    }
}

Integer包装类的常用方法:

例子: Integer 类型和基本数据类型之间的转换,结合运行结果先认识一下吧!

public class HelloWorld {
    public static void main(String[] args) {
         
        // 定义int类型变量,值为86
        int score1 = 86;
         
        // 创建Integer包装类对象,表示变量score1的值
        Integer score2=new Integer(score1);
         
        // 将Integer包装类转换为double类型
        double score3=score2.doubleValue();
         
        // 将Integer包装类转换为float类型
        float score4=score2.floatValue();
         
        // 将Integer包装类转换为int类型
        int score5 =score2.intValue();
 
        System.out.println("Integer包装类:" + score2);
        System.out.println("double类型:" + score3);
        System.out.println("float类型:" + score4);
        System.out.println("int类型:" + score5);
    }
}


//运行结果为:
Integer包装类:86
double类型:86.0
float类型:86.0
int类型:86

Java中基本数据类型和包装类之间的转换

基本类型和包装类之间经常需要互相转换,以Integer为例(其它几个包装类的操作雷同):

基本类型和包装类之间的转换,即装箱和拆箱的操作。

public class HelloWorld {
    public static void main(String[] args) {
         
        // 定义double类型变量
        double a = 91.5;
         
         // 手动装箱
        Double b =new Double(a);       
         
        // 自动装箱
        Double c = a;     
 
        System.out.println("装箱后的结果为:" + b + "和" + c);
         
        // 定义一个Double包装类对象,值为8
        Double d = new Double(87.0);
         
        // 手动拆箱
        double e =d.doubleValue()               ;
         
        // 自动拆箱
        double f = d               ;
         
         System.out.println("拆箱后的结果为:" + e + "和" + f);
    }
}

//运行结果为:
装箱后的结果为:91.5和91.5
拆箱后的结果为:87.0和87.0

Java 中基本类型和字符串之间的转换

在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换。

其中,基本类型转换为字符串有三种方法:

1. 使用包装类的 toString() 方法
2. 使用String类的 valueOf() 方法
3. 用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串

		//将基本数据类型转换为字符串
		 int c = 10;
		 String str1 = Integer.toString(c); //方法一
		 String str2 = String.valueOf(c);   //方法二
		 String str3 = c + ""; //方法三

字符串转换成基本类型有两种方法:

1. 调用包装类的 parseXxx 静态方法

2. 调用包装类的 valueOf() 方法转换为基本类型的包装类,会自动拆箱

		//将字符串转换为基本数据类型
		 String str = "8";
		 int d = Integer.parseInt(str); //方法一
		 int e = Integer.valueOf(str); //方法二

PS:其他基本类型与字符串的相互转化这里不再一一列出,方法都类似
任务:基本类型和字符串之间的转换。

package com.ecc.emp.access;

public class Test {
	public static void main(String[] args) {
        double m = 78.5;
        String str1 =Double.toString(m);    //将基本类型转换为字符串                          ;
        System.out.println("m 转换为String型后与整数20的求和结果为: "+(str1+20));
        String str = "180.20";
        Double a = Double.parseDouble(str); // 将字符串转换为基本类型
        System.out.println("str 转换为double型后与整数20的求和结果为: "+(a+20));
	}
}

//运行结果为:
//m 转换为String型后与整数20的求和结果为: 78.520
//str 转换为double型后与整数20的求和结果为: 200.2

******基本类型是不能调用方法的,而其包装类具有很多方法 *******

1.2 Date 和 SimpleDateFormat类

使用 Date 和 SimpleDateFormat 类表示时间

在程序开发中,经常需要处理日期和时间的相关数据,此时我们可以使用 java.util 包中的 Date 类。

这个类最主要的作用就是获取当前时间,我们来看下 Date 类的使用:

package com.ecc.emp.access;

import java.util.Date;

public class Test {
	public static void main(String[] args) {

		Date d = new Date(); 	//使用默认的构造方法创建Date对象
		System.out.println(d);  //输出Date对象

	}
}

//运行结果为:
//Fri Jan 15 23:24:36 CST 2020

如果想要按指定的格式进行显示,如 2014-06-11 09:22:30 ,那该怎么做呢?

此时就到了 java.text 包中的 SimpleDateFormat 类大显身手的时候了!!可以使用 SimpleDateFormat 来对日期时间进行格式化,如可以将日期转换为指定格式的文本,也可将文本转换为日期。

1. 使用 format() 方法将日期转换为指定格式的文本

import java.text.SimpleDateFormat;
import java.util.Date;
 
public class First {
    public static void main(String []args){
        //创建Date对象,表示当前时间
        Date d=new Date();
        //创建SimpleDateFormat对象,指定目标格式
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //调用format()方法,格式化时间,转换为指定格式字符串
        String today=sdf.format(d);
        //输出转换后的字符串
        System.out.println(today);
    }
}

解释:代码中的 “yyyy-MM-dd HH:mm:ss” 为预定义字符串, yyyy 表示四位年, MM 表示两位月份, dd 表示两位日期, HH 表示小时(使用24小时制), mm 表示分钟, ss 表示秒,这样就指定了转换的目标格式,最后调用 format() 方法将时间转换为指定的格式的字符串。

运行结果为:(当前时间)

2021-01-15 23:54:46

2. 使用 parse() 方法将文本转换为日期

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class First {
    public static void main(String []args){
        //创建SimpleDateFormat对象,指定字符串的日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String day="2016-12-30 14:52:30";  //创建日期格式的字符串
             
            try {
                //调用parse()方法,将字符串转换为日期
                Date date =(Date)df.parse(day);
                //输出转换后的时间
                System.out.println("当前时间;" + date);
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }  
    }
}



//运行结果为:
当前时间;Fri Dec 30 14:52:30 CST 2016

**************************************一定要注意:***********************************
1、 调用 SimpleDateFormat 对象的 parse() 方法时可能会出现转换异常,即 ParseException ,因此需要进行异常处理
2、 使用 Date 类时需要导入 java.util 包,使用 SimpleDateFormat 时需要导入 java.text 包
***************************************************************************************

任务:

功能:实现将日期转换为指定格式的文本,将文本转换为日期

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class HelloWorld {
     
    public static void main(String[] args) throws ParseException {
         
        // 使用format()方法将日期转换为指定格式的文本
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd HH:mm");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         
        // 创建Date对象,表示当前时间
             Date now=new Date();
         
             // 调用format()方法,将日期转换为字符串并输出
        System.out.println(sdf1.format(now));
        System.out.println(sdf2.format(now));
        System.out.println(sdf3.format(now));
 
        // 使用parse()方法将文本转换为日期
        String d = "2014-6-1 21:05:36";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         
         // 调用parse()方法,将字符串转换为日期
        Date date =(Date)sdf.parse(d);
         
        System.out.println(date);
    }
}



//运行结果为:
2021年01月15日 23时45分36秒
2021/01/15 23:45
2021-01-15 23:45:36
Sun Jun 01 21:05:36 CST 2014

1.3 Calendar 类的应用

java.util.Calendar 类是一个抽象类,可以通过调用 getInstance() 静态方法获取一个 Calendar 对象,此对象已由当前日期时间初始化,即默认代表当前时间,
如 Calendar c = Calendar.getInstance();
那么如何使用 Calendar 获取年、月、日、时间等信息呢?
看下面的代码:

import java.util.Calendar;
 
public class First {
    public static void main(String []args){
        //创建Calendar对象
        Calendar c=Calendar.getInstance();
        //获取年
        int year=c.get(Calendar.YEAR);
        //获取月份,0表示1月份
        int month=c.get(Calendar.MONTH)+1;
        //获取日期
        int day=c.get(Calendar.DAY_OF_MONTH);
        //获取小时
        int hours=c.get(Calendar.HOUR_OF_DAY);
        //获取分钟
        int minute=c.get(Calendar.MINUTE);
        //获取秒
        int scond=c.get(Calendar.SECOND);
        //输出结果
        System.out.println("当前时间为:"+year+"-"+month+"-"+day+" "+hours+":"+minute+":"+scond);
         
    }
}


//运行结果为:
当前时间为:2021-1-15 23:48:49

解释:其中,调用 Calendar 类的 getInstance() 方法获取一个实例,然后通过调用 get() 方法获取日期时间信息,参数为需要获得的字段的值, Calendar.Year 等为 Calendar 类中定义的静态常量。

运行结果为:(系统当前时间)

当前时间为:2021-1-15 23:48:49

Calendar 类提供了 getTime() 方法,用来获取 Date 对象,完成 Calendar 和 Date 的转换,还可通过 getTimeInMillis() 方法,获取此 Calendar 的时间值,以毫秒为单位。如下所示:

import java.util.Calendar;
import java.util.Date;
 
public class First {
    public static void main(String []args){
        //创建Calendar对象
        Calendar c=Calendar.getInstance();
        //将Calendar对象转换为Date对象
        Date date=c.getTime();
        //获取当前毫秒数
        Long time=c.getTimeInMillis();
        System.out.println("当前时间:"+date);
        System.out.println("毫秒数:"+time);       
         
    }  
}

运行结果为: (系统当前时间)

当前时间:Fri Jan 15 23:50:13 CST 2021
毫秒数:1610725813585

任务:

实现获取 Calendar 对象,并转换为指定格式的时间。

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
 
public class HelloWorld {
     
    public static void main(String[] args) {
        // 创建Calendar对象
        Calendar c =Calendar.getInstance();
         
        // 将Calendar对象转换为Date对象
        Date date =c.getTime();
         
        // 创建SimpleDateFormat对象,指定目标格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         
        // 将日期转换为指定格式的字符串
        String now = sdf.format(date);
        System.out.println("当前时间:" + now);
    }
}

运行结果为:

当前时间:2021-01-15 23:50:53

1.4  Math 类

使用 Math 类操作数据Math 类位于 java.lang 包中,包含用于执行基本数学运算的方法, Math 类的所有方法都是静态方法,所以使用该类中的方法时,可以直接使用类名.方法名,

如: Math.round();

常用的方法:

public class First {
    public static void main(String []args){
        //定义一个double类型的变量
        double a=12.08;
        //将double类型强制转换 int类型,去掉小数位
        int b=(int) a;
        System.out.println("强制转换为:"+b);
        //调用round方法,进四舍五入
        Long c=Math.round(a);
        System.out.println("返回四舍五入的整数:"+c);
        //调用floor方法,小于参数的最大
        double d=Math.floor(a);
        System.out.println("返回小于参数的最大整数:"+d);
        //调用ceil方法,大于参数的最小
        double e=Math.ceil(a);
        System.out.println("返回大于参数的最小整数:"+e);
        //调用random方法,随机数[0,1)之间的 随机浮点数
        double f=Math.random();
        System.out.println("随机数:"+f);
        //调用random方法,随机[0,99)之间的整数
        int g=(int)(Math.random()*99);
        System.out.println("返回[0,99)之间的随机整数:"+g);
    }  
}

运行结果为:

强制转换为:12
返回四舍五入的整数:12
返回小于参数的最大整数:12.0
返回大于参数的最小整数:13.0
随机数:0.1070699684913281
返回[0,99)之间的随机整数:54

任务

功能:定义一个包含 10 个元素的整型数组,通过随机产生 10 以内的随机数,给数组中的每个元素赋值,并输出结果。

public class First {
    public static void main(String []args){
         // 定义一个整型数组,长度为10
        int[] nums =new int [10];
         
        //通过循环给数组赋值
        for (int i = 0; i < nums.length; i++) {
            // 产生10以内的随机数
            int x =(int)(Math.random()*10);
             
            nums[i] = x;// 为元素赋值
        }
         
        // 使用foreach循环输出数组中的元素
        for (int num:nums) {
            System.out.print(num + " ");
        }
         
    }  
}

运行结果为:(随机数)

6 3 9 0 7 1 1 1 2 7 

1.5 Runtime类

每个Java应用程序都有一个Runtime类的实例,使应用程序能够与其运行环境相连接。不能new,可以通过getRuntime方法获取当前运行时。应用程序不能自己创建自己的Runtime类实例。
可以说,Runtime 封装了Java虚拟机进程。

代码演示:

import java.io.IOException;

public class Test8 {
    public static void main(String[] args) throws IOException,
            InterruptedException {

        // Runtime r=new Runtime();计划这样得到本类实例是错误的

        Runtime r = Runtime.getRuntime();// 要这样得到本类实例

        /*
         * Process的栗子Process p = r.exec("notepad.exe c:/Add.java");//
         * Process代表一个被虚拟机启动的进程p.destroy();
         */

        r.exec("calc");// 打开计算器,没有p.destroy();
        r.exec("mspaint");// 打开画板,没有p.destroy();
        Thread.sleep(5000);// 程序暂停执行5秒
    }
}
 

1.6  Random类

public class Random extands Object implements Serializable。Random类的实例用于生成随机数流。
代码应用例子:

范例一:

import java.util.Random;

//用Java.util.Random类返回20个指定范围(1-10)内的随机整数
//用这个类要构造Random对象
//Random r=new Random(System.currentTimeMillis());设置此随机数生成器的样子
public class Test5 {
    public static void main(String[] args) {
        Random o = new Random();

        for (int i = 0; i < 20; i++) {

            // System.out.println(o.nextInt(10)); 竖着打印随
            // System.out.print(o.nextInt(10)+"\t"); 打算让它横着打印,并且还要好看,需要空格

            // 需求升级,生成90到100之间的数
            // System.out.println(o.nextInt(10)+90);
            System.out.print(o.nextInt(10) + 90 + "\t");// 好看,横着打印,有空格
        }
    }
}

范例二:

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

//从100到题中随机抽取90道
public class Test10 {
    public static void main(String[] args) {
        Set<Integer> list = demo();
        System.out.println(list.size() + "=====");

        for (Integer i : list) {
            System.out.println(i);
        }
    }

    static Set<Integer> demo() {
        Set<Integer> set = new HashSet<Integer>();

        while (set.size() < 90) {
            set.add(new Random().nextInt(100));
        }
        return set;
    }
}
 

范例三:

import java.util.ArrayList;
//import java.util.Collection;
import java.util.Collections;
import java.util.List;

//随机生成1-100之间的100个数,排序无序
public class Test11 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();

        for (int i = 0; i < 100; i++) {
            list.add(i);
        }
        Collections.shuffle(list);// 之前Collections没有写s,导包也导错了

        for (Integer i : list) {
            System.out.print(i + "\t");

        }
    }
}

运行结果为:

1.7  StringUtils工具类

待续

二. 内部类

2.1内部类相关概念

2.1.1 内部类定义

可以将一个类的定义放在另一个类的定义内部,这就是内部类。

public class OuterClass {
    private String name ;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    class InnerClass{
        public InnerClass(){
            name = "chenssy";
            age = 23;
        }
    }
}

在这里InnerClass就是内部类,对于初学者来说内部类实在是使用的不多,但是随着编程能力的提高,我们会领悟到它的魅力所在,它可以使用能够更加优雅的设计我们的程序结构。在使用内部类之间我们需要明白为什么要使用内部类,内部类能够为我们带来什么样的好处。

为什么要使用内部类?

为什么要使用内部类?在《Think in java》中有这样一句话----使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。

public interface Father {

}

public interface Mother {

}

public class Son implements Father, Mother {

}

public class Daughter implements Father{
    class Mother_ implements Mother{
      
    }
}

其实对于这个实例我们确实是看不出来使用内部类存在何种优点,但是如果Father、Mother不是接口,而是抽象类或者具体类呢?这个时候我们就只能使用内部类才能实现多重继承了。

其实使用内部类最大的优点就在于它能够非常好的解决多重继承的问题,但是如果我们不需要解决多重继承问题,那么我们自然可以使用其他的编码方式,但是使用内部类还能够为我们带来如下特性(摘自《Think in java》):
1)内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2)在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
3)创建内部类对象的时刻并不依赖于外围类对象的创建。
4)内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。

5)内部类提供了更好的封装,除了该外围类,其他类都不能访问。

2.1.2 内部类基础

在这个部分主要介绍内部类如何使用外部类的属性和方法,以及使用.this与.new。

当我们在创建一个内部类的时候,它无形中就与外围类有了一种联系,依赖于这种联系,它可以无限制地访问外围类的元素。

public class OuterClass {
    private String name ;
    private int age;

    /**省略getter和setter方法**/
    
    public class InnerClass{
        public InnerClass(){
            name = "chenssy";
            age = 23;
        }
        
        public void display(){
            System.out.println("name:" + getName() +"   ;age:" + getAge());
        }
    }
    
    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();//创建外部类的对象
        OuterClass.InnerClass innerClass = outerClass.new InnerClass(); //使用外部类的对象.new 来创建内部类
        innerClass.display();
    }
}
--------------
Output:
name:chenssy   ;age:23

在这个应用程序中,我们可以看到内部类InnerClass可以对外围类OuterClass的属性进行无缝的访问,尽管它是private修饰的。这是因为当我们在创建某个外围类的内部类对象时,此时内部类对象必定会捕获一个指向那个外围类对象的引用,只要我们在访问外围类的成员时,就会用这个引用来选择外围类的成员。

在这个应用程序中我们还看到了如何来引用内部类,引用内部类我们需要指明这个对象的类型:OuterClasName.InnerClassName。同时如果我们需要创建某个内部类对象,必须要利用外部类的对象通过.new来创建内部类: OuterClass.InnerClass innerClass = outerClass.new InnerClass();。

同时如果我们需要生成对外部类对象的引用,可以使用OuterClassName.this,这样就能够产生一个正确引用外部类的引用了。当然这点实在编译期就知晓了,没有任何运行时的成本。

public class OuterClass {
    public void display(){
        System.out.println("OuterClass...");
    }
    
    public class InnerClass{
        public OuterClass getOuterClass(){
            return OuterClass.this; //生成对外部类的引用,外部类类名.this
        }
    }
    
    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        innerClass.getOuterClass().display();
    }
}
-------------
Output:
OuterClass...

到这里了我们需要明确一点,内部类是个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不同的类(当然他们之间还是有联系的)。对于一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class。

在Java中内部类主要分为成员内部类、局部内部类、匿名内部类、静态内部类。

2.3 成员内部类

成员内部类也是最普通的内部类,它是外围类的一个成员,所以内部类是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问

在成员内部类中要注意两点:

1)成员内部类中不能存在任何static的变量和方法。

2)成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。

public class OuterClass {
    private String str;
    
    public void outerDisplay(){
        System.out.println("outerClass...");
    }
    
    public class InnerClass{//成员内部类,内部类作为外围类的一个成员
        public void innerDisplay(){
            //使用外围内的属性
            str = "chenssy...";
            System.out.println(str);
            //使用外围内的方法
            outerDisplay();
        }
    }
    
    /*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */
    public InnerClass getInnerClass(){
        return new InnerClass(); 
    }
    
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();//成员内部类是依附于外围类的,所以只有先创建了外围类才能创建内部类
        OuterClass.InnerClass inner = outer.getInnerClass();//使用get**()方法获取成员内部类
        inner.innerDisplay();
    }
}
--------------------
chenssy...
outerClass...

推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 。

2.4 局部内部类

有这样一种内部类,它是嵌套在方法和作用域内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

对于局部内部类实在是想不出什么好例子,所以就引用《Think in java》中的经典例子了。

定义在方法里:

public class Parcel5 {
    public Destionation destionation(String str){ //定义在方法中的局部内部类
        class PDestionation implements Destionation{
            private String label;
            private PDestionation(String whereTo){
                label = whereTo;
            }
            public String readLabel(){
                return label;
            }
        }
        return new PDestionation(str);
    }
    
    public static void main(String[] args) {
        Parcel5 parcel5 = new Parcel5();
        Destionation d = parcel5.destionation("chenssy");
    }
}

定义在作用域内:

public class Parcel6 {
    private void internalTracking(boolean b){
        if(b){
            class TrackingSlip{ //定义在作用域中的局部内部类
                private String id;
                TrackingSlip(String s) {
                    id = s;
                }
                String getSlip(){
                    return id;
                }
            }
            TrackingSlip ts = new TrackingSlip("chenssy");
            String string = ts.getSlip();
        }
    }
    
    public void track(){
        internalTracking(true);
    }
    
    public static void main(String[] args) {
        Parcel6 parcel6 = new Parcel6();
        parcel6.track();
    }
}

2.5 匿名内部类

在做Swing编程中,我们经常使用这种方式来绑定事件

button2.addActionListener(  
                new ActionListener(){  
                    public void actionPerformed(ActionEvent e) {  
                        System.out.println("你按了按钮二");  
                    }  
                });

 我们咋一看可能觉得非常奇怪,因为这个内部类是没有名字的,再看如下这个例子:

public class OuterClass {
    public InnerClass getInnerClass(final int num,String str2){
        return new InnerClass(){
            int number = num + 3;
            public int getNumber(){
                return number;
            }
        };        /* 注意:分号不能省 */
    }
    
    public static void main(String[] args) {
        OuterClass out = new OuterClass();
        InnerClass inner = out.getInnerClass(2, "chenssy");
        System.out.println(inner.getNumber());
    }
}

interface InnerClass {
    int getNumber();
}

----------------
Output:
5

这里我们就需要看清几个地方:
1) 匿名内部类是没有访问修饰符的。
2) new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。
3) 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
4) 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

PS:由于篇幅有限,对匿名内部类就介绍到这里,有关更多关于匿名内部类的知识,我就会在下篇博客(java提高篇-----详解匿名内部类)做详细的介绍,包括为何形参要定义成final,怎么对匿名内部类进行初始化等等,敬请期待……

2.6  静态内部类

在Java提高篇-----关键字static中提到Static可以修饰成员变量、方法、代码块,其实它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
1) 它的创建是不需要依赖于外围类的。

2) 它不能使用任何外围类的非static成员变量和方法。

public class OuterClass {
    private String sex;
    public static String name = "chenssy";
    
    /**
     *静态内部类
     */
    static class InnerClass1{
        /* 在静态内部类中可以存在静态成员 */
        public static String _name1 = "chenssy_static";
        
        public void display(){
            /* 
             * 静态内部类只能访问外围类的静态成员变量和方法
             * 不能访问外围类的非静态成员变量和方法
             */
            System.out.println("OutClass name :" + name);
        }
    }
    
    /**
     * 非静态内部类
     */
    class InnerClass2{
        /* 非静态内部类中不能存在静态成员 */
        public String _name2 = "chenssy_inner";
        /* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
        public void display(){
            System.out.println("OuterClass name:" + name);
        }
    }
    
    /**
     * @desc 外围类方法
     * @author chenssy
     * @data 2013-10-25
     * @return void
     */
    public void display(){
        /* 外围类访问静态内部类:内部类. */
        System.out.println(InnerClass1._name1);
        /* 静态内部类 可以直接创建实例不需要依赖于外围类 */
        new InnerClass1().display();
        
        /* 非静态内部的创建需要依赖于外围类 */
        OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
        /* 方位非静态内部类的成员需要使用非静态内部类的实例 */
        System.out.println(inner2._name2);
        inner2.display();
    }
    
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.display();
    }
}
----------------
Output:
chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy

上面这个例子充分展现了静态内部类和非静态内部类的区别。

------------------------------------------------------------------ 我是低调的分隔线  ----------------------------------------------------------------------

                                                                                                                                     吾欲之南海,一瓶一钵足矣...

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值