Java基础

目录

语法

        数组

 # 数组的初始化

 # 数组引用

# 数组的遍历

# 二维数组

修饰符

        类修饰符:

        方法修饰符:

内存结构

 Java堆(Heap)

JVM(JVM Stacks)

方法区(Method Area)

程序计数器(Program Counter Register)

本地方法栈(Natice Method Stacks)

Java内存模型

 Java对象模型

集合

# HashSet

# ArrayList

# ListIterator

# HashMap

# WeekHashMapDemo

反射

一、反射机制的概念:

二、反射机制的应用:

三、反射机制的原理:


语法

        循环

                for循环:

public class xunHun{
    public static void main(String[] args){
        int sum=0;
        int i=0;
        for(i=0;i<=100;i++){
            sum=sum+i;
        }
        Systme.out.println(sum);
    }
}

                switch循环

switch(key){
    case value:
    break;
    default:
    break;
}

int a=3;
switch(a){
    case 1:
        System.out.println("1.绿茶 3元");
    break;
    case 2:
        System.out.println("2.红茶 3元");
    break;
    case 3:
        System.out.println("3.脉动 4元");
    break;
    default:
        System.out.println("无此商品");
    break;
}

                do while:

代码示例为:
do{
}while(condition);括号内为循环条件
使用方法:一般用于循环次数不确定的循环,与while循环不同的是dowhile循环先执行后判断,至少执行一次,

实例:
int j=1;
int sum2=0;
do{
    if(j%5==0&&(j%7==0))
    sum2+=j;
    j++;
}while(j<=100);
System.out.prinlt("100以内既能被5整除又能被7整除数的和"+sum2);

        数组

java中定义数组的语法有两种:

type arrayName[];

type[] arrayName;

type为Java中的任意数据类型,包含基本类型和组合类型,arrayName为数组名,必须是一个合法的标识符,[]指明该变量是一个数组类型变量。例如:

int demoArray[];

int[] demoArray;

这两种形式没有区别,使用效果完全一样,读者可根据自己的编程习惯选择。

与C、C++不同,Java在定义数组时并不为数据元素分配内存,因此[]中无需指定数组元素的个数,即数组长度。而且对于如上定义的一个数组是不能访问他的任何元素的,我们必须要为它分分配内存空间,这时要用到运算符new,其格式如下:

demoArray=new int[3];

为一个整型数组分配3个int型整数所占据的内存空间。

通常,你可以在定义的同时分配空间,

type arrayName[]=new type[arraySize];

例如:

int demoArray[]=new int[3];

 # 数组的初始化

你可以在声明数组的同时进行初始化(静态初始化),也可以在声明以后进行初始化(动态初始化)。例如:

1.//静态初始化

2.//静态初始化的同时

3.int intArray[]={1,2,3,4};

4.String stringArray[]={"微学苑"};

5.//动态初始化

6.float floatArray[]=new float[3];

7.floatArray[0]=1.0f;

8.floatArray[1]=132.63f;

floatArray[2] =100F;

 # 数组引用

可以通过下标来引用数组:

arrayName[index];

与C、C++不同,Java对数组元素要进行越界检查以保证安全性。

每个数组都有一个length属性来指明它的长度,例如intArray.length指明数组intArray的长度。

import java.util.*;
public class Demo {
    public static void main(String[] args){
        int intArray[] = new int[5];
        long total = 0;
        int len = intArray.length;
        // 给数组元素赋值
        System.out.print("请输入" + len + "个整数,以空格为分隔:");
        Scanner sc = new Scanner(System.in);
        for(int i=0; i<len; i++){
            intArray[i] = sc.nextInt();
        }
        // 计算数组元素的和
        for(int i=0; i<len; i++){
            total += intArray[i];
        }
        System.out.println("所有数组元素的和为:" + total);
    }
}

运行结果:

请输入5个整数,以空格为分隔:10 20 15 25 50

所有数组元素的和为:120

# 数组的遍历

实际开发中,经常需要遍历数据以获取数组中的每一组元素。做容易想到的方法是for循环,例如:

int arrayDemo[]={1,2,4,7,9,192,100};
for(int i=0,len=arrayDemo.length;i<len;i++){
    System.out.println(arrayDemo[i]+",");
}
输出结果:
1,2,4,7,9,192,100

不过,Java提供了"增强版"的for循环,专门用来遍历数组,语法为:

for(arrayType varName:arrayName){
    //Some Code
}

arrayType为数组类型(也是数组元素的类型);varName是用来保存当前元素的变量,每次循环它的值都会改变;arrayName为数组名称。

每循环一次,就会获取数组中下一个元素的值,保存到varName变量,直到数组结束。即,第一次循环varName的值为第0个元素,第二次循环为第1个元素......

例如:

int arrayDemo[]={1,2,4,7,192,100};
for(int x:arrayDemo){
    System.out.println(x+",");
}

输出结果与上面相同。

这种增强版的for循环也被称为"foreach",它是普通for循环语句的特殊简化版。所有foreach循环都可以被改写成for循环。

但是,如果你希望使用数组的索引,那么增强版的for循环无法做到。

# 二维数组

二维数组的声明、初始化和引用与一堆数组相似:

int intArray[][]={{1,2},{2,3},{4,5}};
int a[][]=new int[2][3];
a[0][0]=12;
a[0][1]=34;
a[1][2]=93;

Java语言中,由于把二维数据看作是数组的数组,数组空间不是连续分配的,所以不要求二维数组每一维的大小相同。例如:

int intArray[][]={{1,2},{2,3},{3,4,5}};
int a[][]=new int[2][];
a[0]=new int[3];
a[1]=new int[5];


[示例]通过二维数组计算两个矩形的乘积。
public class Demo{
    public static void main(String[] args){
        int a[][]=new int[2][3];
        int b[][]={{1,5,2,8},{5,9,10,-3},{2,7,-5,-18}};
        int c[][]=new int[2][4];

        for(int i=0;i<2;i++)
        for(int j=0;j<3;j++)
        a[i][j]=(i+1)*(j+2);
        for(int i=0;i<2;i++){
            for(int j=0;j<4;j++){
                c[i][j]=0;
                for(int k=0;k<3;k++){
                    c[i][j]+=a[i][k]*b[k][j];
                }
            }
            //输出结算结果
            for(int i=0;i<2;i++){
                for(int j=0;j<4;j++){
                    System.out.println("%-5d",c[i][j]);
                    System.out.println();
                }
            }
        }
    }
}
运行结果 25    65    14    -65
        50    130   28    -130

几点说明:

上面讲的是静态数组。静态数组一旦被声明,它的容量就固定了,不容改变。所以在声明数组时,一定要考虑数组的最大容量,防止容量不够的现象。

如果想在运行程序时改变容量,就需要用到数组列表(ArrayList,也称动态数组)或向量(Vector)。

正是由于静态数组容量固定的缺点,实际开发中使用频率不高,被ArrayList或Vector代替,因为实际开发中经常需要向数组中添加或删除元素,而它的容量不好预估。

修饰符

        类修饰符:

                public(公共访问控制符):指定该变量为公共的,他可以被任何对象的方法访问。

                private(私有访问控制符):指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。

                protected(保护访问控制符):指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。

                friendly:在同一个包类可以访问,其他包中的类不能访问。

                final:最终修饰符,指定此变量的值不能变。

                static(静态修饰符):指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。

                transient(过度修饰符):指定该变量时系统保留,暂无特别作用的临时性变量。

                volatile(易失修饰符):指定该变量可以同时被几个线程控制和修改。

        方法修饰符:

                public(公共控制符)

                private(私有控制符)

                protected(保护控制符)

                final:指定该方法不能被重载

                static:指定不需要实例化就可以激活的一个方法。

                synchronize:同步修饰符,在多个线程中,该修饰符用于在运行前,对他所属的方法加锁,以防止其他线程的访问,运行结束后解锁。

                native:本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的。

内存结构

å¨è¿éæå¥å¾çæè¿°

 JVM内存结构主要有三大块:堆内存、方法区和栈。

堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分为三部分,Eden空间、From Survivor空间、To Survivor空间,默认情况下年轻代按照8:1:1的比例来分配;

方法区存储类信息、常量、静态变量等数据,是线程共享的区域,为与Java堆区分,方法区还有一个别名Non-Heap(非堆);

栈又分为java虚拟机和本地方法栈,主要用于方法的执行。

控制参数:

-Xms设置堆的最小空间大小。

-Xms设置堆的最大空间大小。

-XX:NewSize:设置新生代最小空间大小。

-XX:MaxNewSize:设置新生代最大空间大小。

-XX:PermSize:设置永久代最小空间大小。

-XX:MaxPermSize:设置永久代最大空间大小。

-Xss:设置每个线程的堆栈大小。

没有直接设置老年代的参数,但是可以设置堆空间大小和新生代空间大小两个参数来间接控制。

老年代空间大小=堆空间大小-年轻代空间大小

å¨è¿éæå¥å¾çæè¿°

 Java堆(Heap)

对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆时被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

Java堆时垃圾收集器管理的主要区域,因此很多时候也被称做"GC堆"。如果从内存回收的角度看,由于现在收集器基本都是采用分代手机算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。

根据Java虚拟机规范的规定,Java堆可以处于物理上下不连续的内存空间中,只要逻辑上时连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。

如果在堆中没有内存完成实例分配,并且堆也无法在扩展时,将会抛出OutOfMemoryError异常。

JVM(JVM Stacks)

与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作堆栈、动态链接、方法出口等信息。每一个方法都被调用直至执行完成的过程,就对应这一个栈帧在虚拟机中从入栈到出栈的过程。

局部变量表存放了编译器可知的各种基数数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,他不等同于对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象的位置)和returnAddress类型(指向了一条字节码指定的地址)

其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用一个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所运行的深度,将抛出StackOverflowError异常,如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也运行固定长度的虚拟机栈),当扩展时无法申请大足够的内存时会抛出OutOfMemoryError异常。

方法区(Method Area)

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。

对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为"永久代"(Permanebt Generation),本质上两只并不等价,仅仅是因为HosSpot虚拟机的设计团队选择把GC分带手机扩展至方法区,或者说使用永久代来实现方法区而已。

Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要连接内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样"永久"存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收"成绩"比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实有必要的。

根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMeoryError异常。

程序计数器(Program Counter Register)

程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更搞笑的方法区实现),字节码解释器工作是就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

由于Java虚拟机的多线程是通过线程轮流切换并分配处理执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核),只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计算器,各条线程之间的计算器互不影响,独立存储,我们称这类内存区域为"线程私有"的内存。

如果线程正在执行的是一个Java方法,这个计算器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计算器值则为空(Undefined)。

此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

本地方法栈(Natice Method Stacks)

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方法与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryErrot异常。

Java内存模型

å¨è¿éæå¥å¾çæè¿°

 Java对象模型

å¨è¿éæå¥å¾çæè¿°

集合

上述类图中,实线边款的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等。

发现一个特点,上述所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法。它的一个子接口LinkedIterator在它的基础上又添加了三种方法,分别是add(),previous(),hasPrevious()。也就是说如果是先Iterator接口,那么在遍历集合中元素的时候,只能往后遍历,被遍历后的元素不会在遍历到,通常无序集合实现的都是这个接口,比如HashSet,HashMap;而那些元素有序的集合,实现的一般都是LinkedIterator接口,实现这个接口的集合可以双向遍历,既可以通过next()访问下一个元素,又可以通过previous()访问前一个元素,比如ArrayList。

还有一个特点就是抽象类的使用。如果要自己实现一个集合类,去实现那些抽象的接口会非常麻烦,工作量很大。这个时候就可以使用抽象类,这些抽象类中给我们提供了许多现成的实现,我们只需要根据自己的需求重写一些方法或者或者添加一些方法就可以实现自己需要的集合类,工作流昂大大降低

# HashSet

HashSet是Set接口的一个子类,主要的特点是:里面不能存放重复元素,而且采用散列的存储方法,所有没有顺序。这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致。

代码实例:HashSetDemo

View Code 

package edu.sjtu.erplab.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetDemo {

    public static void main(String[] args) {
        Set<String> set=new HashSet<String>();
        
        set.add("a");
        set.add("b");
        set.add("c");
        set.add("c");
        set.add("d");
        
        //使用Iterator输出集合
        Iterator<String> iter=set.iterator();
        while(iter.hasNext())
        {
            System.out.print(iter.next()+" ");
        }
        System.out.println();
        //使用For Each输出结合
        for(String e:set)
        {
            System.out.print(e+" ");
        }
        System.out.println();
        
        //使用toString输出集合
        System.out.println(set);
    }
}

代码实例:SetTest

View Code 

package edu.sjtu.erplab.collection;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class SetTest {

    public static void main(String[] args) throws FileNotFoundException {
        Set<String> words=new HashSet<String>();

        //通过输入流代开文献
        //方法1:这个方法不需要抛出异常
        InputStream inStream=SetTest.class.getResourceAsStream("Alice.txt");
        
        //方法2:这个方法需要抛出异常
        //InputStream inStream = new FileInputStream("D:\\Documents\\workspace\\JAVAStudy\\src\\edu\\sjtu\\erplab\\collection\\Alice.txt");
        Scanner in=new Scanner(inStream);
        while(in.hasNext())
        {
            words.add(in.next());
        }
        
        Iterator<String> iter=words.iterator();
        
        for(int i=0;i<5;i++)
        {
            if(iter.hasNext())
            System.out.println(iter.next());
        }
        
        System.out.println(words.size());

    }
}

# ArrayList

ArrayList是List的子类,它和HashSet想法,允许存放重复元素,因此有序。集合中元素被访问的顺序取决于集合的类型。如果对ArrayList进行访问,迭代器将从索引0开始,每迭代一次,索引值加1。然而,如果访问HashSet中的元素,没个元素将会按照某种随机的次序出现。虽然可以确定在迭代中能够遍历到集合中的所有元素,但却无法预知被访问的次序。

View Code 
package edu.sjtu.erplab.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListDemo {
    public static void main(String[] args) {
        List<String> arrList=new ArrayList<String>();
        
        arrList.add("a");
        arrList.add("b");
        arrList.add("c");
        arrList.add("c");
        arrList.add("d");

        //使用Iterator输出集合
        Iterator<String> iter=arrList.iterator();
        while(iter.hasNext())
        {
            System.out.print(iter.next()+" ");
        }
        System.out.println();
        //使用For Each输出结合
        for(String e:arrList)
        {
            System.out.print(e+" ");
        }
        System.out.println();
        
        //使用toString输出集合
        System.out.println(arrList);
    }
}

# ListIterator

View Code 

package edu.sjtu.erplab.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class LinkedListTest {

    public static void main(String[] args) {

        List<String> a=new ArrayList<String>();
        a.add("a");
        a.add("b");
        a.add("c");
        System.out.println(a);
        
        List<String> b=new ArrayList<String>();
        b.add("d");
        b.add("e");
        b.add("f");
        b.add("g");
        System.out.println(b);
        
        //ListIterator在Iterator基础上添加了add(),previous()和hasPrevious()方法
        ListIterator<String> aIter=a.listIterator();
        //普通的Iterator只有三个方法,hasNext(),next()和remove()
        Iterator<String> bIter=b.iterator();
        
        //b归并入a当中,间隔交叉得插入b中的元素
        while(bIter.hasNext())
        {
            if(aIter.hasNext())
                aIter.next();
            aIter.add(bIter.next());
        }
        System.out.println(a);
        
        //在b中每隔两个元素删除一个
        bIter=b.iterator();
        
        while(bIter.hasNext())
        {
            bIter.next();
            if(bIter.hasNext())
            {
                bIter.next();//remove跟next是成对出现的,remove总是删除前序
                bIter.remove();
            }
        }
        System.out.println(b);
        
        //删除a中所有的b中的元素
        a.removeAll(b);
        System.out.println(a);
    }
}

# HashMap

# WeekHashMapDemo

View Code 

package edu.sjtu.erplab.collection;

import java.util.WeakHashMap;

public class WeekHashMapDemo {

    public static void main(String[] args) {
        int size = 100;

        if (args.length > 0) {
            size = Integer.parseInt(args[0]);
        }

        Key[] keys = new Key[size];
        WeakHashMap<Key, Value> whm = new WeakHashMap<Key, Value>();

        for (int i = 0; i < size; i++) {
            Key k = new Key(Integer.toString(i));
            Value v = new Value(Integer.toString(i));
            if (i % 3 == 0) {
                keys[i] = k;//强引用
            }
            whm.put(k, v);//所有键值放入WeakHashMap中
        }

        System.out.println(whm);
        System.out.println(whm.size());
        System.gc();
        
        try {
            // 把处理器的时间让给垃圾回收器进行垃圾回收
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
        
        System.out.println(whm);
        System.out.println(whm.size());
    }

}

class Key {
    String id;

    public Key(String id) {
        this.id = id;
    }

    public String toString() {
        return id;
    }

    public int hashCode() {
        return id.hashCode();
    }

    public boolean equals(Object r) {
        return (r instanceof Key) && id.equals(((Key) r).id);
    }

    public void finalize() {
        System.out.println("Finalizing Key " + id);
    }
}

class Value {
    String id;

    public Value(String id) {
        this.id = id;
    }

    public String toString() {
        return id;
    }

    public void finalize() {
        System.out.println("Finalizing Value " + id);
    }

}
View Code 

{50=50, 54=54, 53=53, 52=52, 51=51, 46=46, 47=47, 44=44, 45=45, 48=48, 49=49, 61=61, 60=60, 63=63, 62=62, 65=65, 64=64, 55=55, 56=56, 57=57, 58=58, 59=59, 76=76, 75=75, 74=74, 73=73, 72=72, 71=71, 70=70, 68=68, 69=69, 66=66, 67=67, 85=85, 84=84, 87=87, 86=86, 81=81, 80=80, 83=83, 82=82, 77=77, 78=78, 79=79, 89=89, 88=88, 10=10, 90=90, 91=91, 92=92, 93=93, 94=94, 95=95, 96=96, 97=97, 98=98, 99=99, 20=20, 21=21, 12=12, 11=11, 14=14, 13=13, 16=16, 15=15, 18=18, 17=17, 19=19, 8=8, 9=9, 31=31, 4=4, 32=32, 5=5, 6=6, 30=30, 7=7, 0=0, 1=1, 2=2, 3=3, 29=29, 28=28, 27=27, 26=26, 25=25, 24=24, 23=23, 22=22, 40=40, 41=41, 42=42, 43=43, 38=38, 37=37, 39=39, 34=34, 33=33, 36=36, 35=35}
100
Finalizing Key 98
Finalizing Key 97
Finalizing Key 95
Finalizing Key 94
Finalizing Key 92
Finalizing Key 91
Finalizing Key 89
Finalizing Key 88
Finalizing Key 86
Finalizing Key 85
Finalizing Key 83
Finalizing Key 82
Finalizing Key 80
Finalizing Key 79
Finalizing Key 77
Finalizing Key 76
Finalizing Key 74
Finalizing Key 73
Finalizing Key 71
Finalizing Key 70
Finalizing Key 68
Finalizing Key 67
Finalizing Key 65
Finalizing Key 64
Finalizing Key 62
Finalizing Key 61
Finalizing Key 59
Finalizing Key 58
Finalizing Key 56
Finalizing Key 55
Finalizing Key 53
Finalizing Key 52
Finalizing Key 50
Finalizing Key 49
Finalizing Key 47
Finalizing Key 46
Finalizing Key 44
Finalizing Key 43
Finalizing Key 41
Finalizing Key 40
Finalizing Key 38
Finalizing Key 37
Finalizing Key 35
Finalizing Key 34
Finalizing Key 32
Finalizing Key 31
Finalizing Key 29
Finalizing Key 28
Finalizing Key 26
Finalizing Key 25
Finalizing Key 23
Finalizing Key 22
Finalizing Key 20
Finalizing Key 19
Finalizing Key 17
Finalizing Key 16
Finalizing Key 14
Finalizing Key 13
Finalizing Key 11
Finalizing Key 10
Finalizing Key 8
Finalizing Key 7
Finalizing Key 5
Finalizing Key 4
Finalizing Key 2
Finalizing Key 1
{54=54, 51=51, 45=45, 48=48, 60=60, 63=63, 57=57, 75=75, 72=72, 69=69, 66=66, 84=84, 87=87, 81=81, 78=78, 90=90, 93=93, 96=96, 99=99, 21=21, 12=12, 15=15, 18=18, 9=9, 6=6, 30=30, 0=0, 3=3, 27=27, 24=24, 42=42, 39=39, 33=33, 36=36}
34

3.比较

  是否有序是否允许元素重复
Collection
List
SetAbstractSet
 HashSet
 TreeSet是(用二叉排序树)
MapAbstractMap使用key-value来映射和存储数据,key必须唯一,value可以重复
 HashMap
 TreeMap是(用二叉排序树)

反射

一、反射机制的概念:

指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法,这种动态获取信息,以及动态调用对象方法的功能叫java语言的反射机制。

二、反射机制的应用:

生成动态代理,面向切片编程(在调用方法的前后各加栈帧)

三、反射机制的原理:

1.首先明确的概念:一切皆对象--类也是对象.

2.然后知道类中的内容:modifier constructor field method

3.其次明白加载:当Animal.class在硬盘中时,是一个文件,当载入到内存中,可以认为是一个对象,是java.lang.class的对象

当运行程序时,实例化时产生Animal.class对象,这两个对象有什么区别?

如下图,上面的Animal.class对象是java.lang.class的对象;下面的对象是Animal.class实例化产生的对象

3dd15a3164fcefdba83b5cf7b6f6b80.png

4.当Animal.class载入到JVM中,JVM是怎么识别Animal.class中含有的方法,成员变量,构造方法等内容?

如下图,Animal.class实例化对象中成员变量 毛色=红色

加载到内存的时候,毛色=null,是在实例化的时候毛色被赋值为红色

6871eedafd27eacc1b72ac8521ed203.png

 Animal.class中毛色这个属性对于java.lang.class来说,是Field的一个属性值,毛色对于java.lang.class来说也是一个对象,这也是反射机制动态获取信息,以及动态调用对象方法的原因.

下图是Java.lang.class中的方法:

6871eedafd27eacc1b72ac8521ed203.png

e2d5681d61b580beaa4f02e5143bce6.png

59f2f39ea2a30acadf537febea9449e.png

在java.lang.class中,毛色是Field的一个属性值,Animal中所有的方法,成员变量,构造器,修饰符都是按照java.lang.class中的标准去写的,否则会在编译的时候报错

6e48ebbf9d537f840cabe8156a3dcbf.png

 反射机制简单实例代码

public class _14_ReflectTest07

{

     public static void main(String[] args) throws Exception{

         //1.获取类

         Class c = Class.forName("_12_CustomerService");

         //获取某个特定的方法

         //通过:方法名+形参列表

         Method m = c.getDeclaredMethod("login",String.class,String.class);

         //通过反射机制执行login方法.

         Object o = c.newInstance();

         //调用o对象的m方法,传递"admin""123"参数,方法的执行结果是retValue

         Object retValue = m.invoke(o, "admin","123");

         System.out.println(retValue); //true

     }

}

  

  

  

public class _12_CustomerService

{

     //登录

     public boolean login(String name,String pwd){

         if("admin".equals(name) && "123".equals(pwd)){

              return true;

         }

         return false;

     }

     //退出

     public void logout(){

         System.out.println("系统已安全退出!");

     }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值