黑马程序员Java基础第六章-----内部类,对象的产生过程,所有的超类Object,包,String类

来源:互联网 发布:五子棋c语言代码 编辑:程序博客网 时间:2024/06/05 02:36

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

一.内部类

1.内部类的概念:一个类在另外一个类的内部,那么这个类就叫内部类,另一个类叫做外部类

2.内部类的表现形式:

class  A

{

        int num ;

        void display(){......}

        class B

        {

               int  age ;

               void show(){........}

        }

}

所以,可以发现内部类也是一个完整的类,也具有类的所有的组成部分,它只是被定义在了另一个类的内部而已。

3.内部类的好处:内部类可以直接访问外部类的所有的成员(包括私有的,因为是在A的本类中访问),此时内部类相当于外部类的一个成员也可以被成员修饰符修饰,具有成员的访问特性,这样就可以隐藏不想对外暴露的类(Iterator的子类就实现在各集合的内部)。

4.修饰内部类的修饰符

权限修饰符:

          1)public:表明内部类可以被外部的第3方类访问,定义对象

          2)protect:可以被子类访问

          3)默认权限:可以被包中的类访问

          4)private:内部类只能在本外部类中访问,不能被第3方类访问,对本包中的其他的起到了隐藏作用。

静态修饰符:static:内部类在成员上时也可以被静态修饰,此时的内部类叫做静态内部类

         1)静态内部类随着外部类的加载而加载

         2)静态内部类只能访问外部类静态成员

         3)静态内部类中可以有静态成员也可以有非静态成员

         4)有静态成员的内部类一定是静态内部类

5.内部类的另一种形式:匿名内部类:匿名内部类是指没有名字的内部类。我们可以直接new对象的时候,实现该类中未实现的方法,实际上创建的对象是该类的子类的对象。

abstract class A

{

     abstract void method();

}

class B

{

       void excute()

       {

             new A()

             {

                   void method()

                    {

                           执行代码

                    }

             }.method();

       }

}

1)匿名内部类实际上就是一个匿名的子类对象

2)A类可以是抽象类,可以是接口,也可以普通的类,被重写的方法也可以是普通的方法,抽象方法。

3)new A().......就是一个匿名内部类,创建的实际上是一个A类的子类的对象。

4)匿名内部类只能使用一次,因为这个类没有名称,不能再次调用

5)匿名内部类不能包含static成员,从父类继承的可以,不能自己增加。(因为有static成员的内部类是静态内部,new的时候在类上没有办法声明static)

6)匿名内部类若出现在函数的参数中时,此时实际上时多态,将匿名内部类(是一个子类)赋给父类的引用。调用时不能直接调用子类新增的方法和变量。

6.内部类,外部类,第3方类的访问关系:

说明:1.内部类中有静态成员,该内部类是静态内部类。

           2.静态内部类中的方法(无论是否静态)只能访问外部类的静态方法。

           3.外部类的静态方法只能访问静态内部类。

           4.当内部类中的方法中,内部类的成员位置出现了和外部类相同成员变量,内部类中访问局部可以直接写变量名,访问内部类中的要加this不能省略,要访问外部类中的要使用外部类名.this.引用不能省略。当没有相同时,可以省略不写,会默认加上。

           5.匿名内部类可以应用于接口回调,可以用于开发事件驱动。

二.对象的产生过程

我们使用new来创建一个对象时,内存中构建对象的执行流程是:

1.不考虑继承关系时,执行流程:

2.当考虑继承关系时,创建子类的对象:

1).执行父类的静态代码块

2).在执行子类的静态代码块。

3).在执行父类的构造函数

4).最后执行子类的构造函数。

没有写出中间其他的执行步骤。若再一次的创建子类对象,会在执行一次3和4,1和2不会执行。因为类加载时静态代码块才会执行一次,静态代码块是给类变量初始化的,而类变量随着类的加载而加载,此时静态代码块执行一次对类变量初始化。类加载进内存中后,以后创建对象不再加载类,静态代码块也不再执行。

3.引起类字节码文件加载进内存的情况:new创建对象;调用类的静态的方法;

三.超类Object(上帝)

Object类是java中所有的类的直接或者间接的父类,它提供了每个类都需要的最一般的一些方法。

1.equals方法:这个方法是比较两个对象是否相等。但是使用的方式是比较两个对象地址的方法,因此我们在写java类时都要重写这个方法,改成比较对象内容的方式。在很多的地方会用这个函数,比如:List集合的判断和删除元素时会用到,HashSet中也要用到。所有的包装类和String类都重写了这个方法。

2.toString方法:这个方法是输出对象的类名@Integer.toHexString(hasCode());输出的是类名加上地址的哈希值的16进制形式,我们也要复写这个方法,改成输出对象成员值的方式。String类重写了这个方法。

3.hasCode方法:地址的哈希值。创建java类时要复写,在集合中的HashSet保证元素的唯一性,不重复就要调用这个方法和equals方法,HashMap和Hashtable也会用到

4.await方法:是正在知执行的线程处于冻结状态。notify:唤醒冻结的线程,线程进入线程池等待被唤醒。notifyAll:唤醒线程池中所有的冻结线程。

四.包

1.包的概念:为了避免类名重复冲突而采取的将类分包存放,包名用一串小写字母表示,在工程中保证唯一。

2.包的好处:1.将java类和.class字节码文件分开存放,有效管理

                     2.避免了类名的冲突,可以将同名的类放在不同的包中

                     3.可以将java类按照功能分包存放,将包名取一个有意义的名称,便于项目的统一管理

3.包用到的关键字:package   import

package:写在java类的第一行,表示这个类所属的包。如:package  com.itheima.util。这是一个工具类的包

import:使用来导入包中的类的关键字

             import  java.io.*;是导入io包中的所有的类。如果io包中包含子包,子包中的类不会导入进来。

             import java.io.File;是导入一个File类。不导入io包中的其他的类。*是导入所有的类

4.java中打包Dos命令行:java  -d  c:\   A.java。  c:\  是指将生成的包放在哪个文件目录下    A.java是要编译的类

此时,java的全类名就成了:包名.类名 。执行java程序:java  包名.类名

包生成后其实就是多层的文件夹,文件夹名和包名的每一段对应。

五.String

1.这个类表示一个字符串类。“abc”就表示一个字符串对象。字符串对象是一个常量,只要初始化后就不能被改变。

当String  s1 = "abc";  s1 = "xyz";这时候并不是改变了字符串的值,而只是改变了引用的指向而已。因为字符串abc和xyz都在内存中,开始s1指向了字符串对象abc,后来又指向了字符串对象xyz,字符串对象的值并没有发生改变。abc还在内存中,我们是无法改变abc的值的。

2.字符串的类型是引用类型,存储在堆内存中。默认初始化值是null。当字符串对象“abc”,没有引用指向时,就会变成垃圾,会被GC在某个合适的时间回收。

3.字符串比较相等,不能使用==,要使用equals方法(java重写了String的equals方法,比较的是对象的内容),对于引用类型==比较的是内存地址。

4.字符串的操作:

1)字符串的构造:String  s = "abc" ;栈内存中的引用变量s指向对像abc。

                              String  s;定义了一个栈内存中的局部变量,不会被初始化,没有指向任何地址。定义在一个类中,new对象时,堆内存会对s初始化为null。

                              String s = new String();s指向了堆内存中的String对象,此时s的值是“”空字符串。所以在String对象的内部对对象进行了赋值。

                              String  s = new String("abc");和String s = “abc”的区别:第一个在内存中有两个对象。第二句话在内存中只有一个对象。

2)获取:charAt获取指定位置的字符。substring获取指定索引位置的子串。getBytes获取字符串的字节数组。length获取字符串的长度

3)判断:equals判断两个字符串是否相等。endsWith,startWith以什么开始,以什么结束。contains是否包含某个子串。isEmpty是否为空。

4)查找:indexOf查找子串又返回位置,没有则返回-1。lastIndexOf从后向前查找子串

4)切割:split方法可以用来对字符串进行切割,把字符串变为多个子串,放在数组中返回。参数可以是字符串也可以是正则表达式。

5)替换:replace替换字符串中的一部分

6)匹配:matches按照某一规则返回字符串是否匹配,规则在内部被封装成正则表达式。

六.代码练习

class Outer{//对成员进行显示初始化private String addr = "北京" ;int num = 6 ;//内部类class Inner{//内部类的成员变量int num = 8 ;void show(){//局部变量int num = 9 ;//访问的是局部变量System.out.println("局部变量num="+num);//访问的是内部类的成员System.out.println("内部类的num="+this.num);//访问的是外部类的成员(内部类可以访问外部类的所有的成员,包括私有)System.out.println("外部类的num="+Outer.this.num);            //访问的是外部类的私有成员(内部类可以访问外部类的所有的成员,包括私有),当内部类没有和外部类同名//的成员时,外部类.this.  这个外部类的引用可以省略System.out.println("外部类的addr="+addr);}}void display(){//外部类访问内部类要创建内部类的对象new Inner().show();}}interface Inter{void invoke();}class InterClass {public static void main(String[] args) {Outer out = new Outer();out.display();//匿名内部类new Inter(){public void invoke(){System.out.println("匿名内部类调用");}}.invoke();}}

运行结果:







0 0