黑马程序员--Java学习日记之类的加载,反射,动态代理,枚举

1 篇文章 0 订阅
1 篇文章 0 订阅

 

                                            ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


一、类的加载

1、类的加载相关概述

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三步来对这个类进行初始化。

①加载

  • 就是指将class文件读入内存,并为之创建一个Class对象
  • 任何类被使用时系统都会建立一个Class对象。

②连接

  • 验证 是否有正确的内部结构,并和其他类协调一致
  • 准备 负责为类的静态成员分配内存,并设置默认初始化值
  • 解析 将类的二进制数据中的符号引用替换为直接引用
③初始化:跟以前的初始化动作一样。

2、类加载器

①概念:负责将.class文件加载到内存中,并为之生成对应的Class对象。

②类加载器的组成:

  • Bootstrap Classloader根类加载器。也称为引导类加载器负责java核心类的加载,比如System.String等。在JDK中JRE的lib目录下rt.jar文件中。
  • Extension ClassLoader扩展类加载器。负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下的ext目录。
  • System CkassLoader 系统类加载器,负责在JVM启动时加载来自java命令的class文件,以及负责classpath环境变量所指定的jar包和路径。主要是用来加载我们写的文件。

二、反射

1、反射的基石——Class类

①所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class(描述字节码文件的对象)。

  • Class类中就包含属性有field(字段)、method(方法)、construction(构造函数)。
  • 而field中有修饰符、类型、变量名等复杂的描述内容,因此也可以将字段封装称为一个对象。用来获取类中field的内容,这个对象的描述叫Field。同理方法和构造函数也被封装成对象Method、Constructor。要想对一个类进行内容的获取,必须要先获取该字节码文件的对象。该对象是Class类型。
  • Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等。每一个字节码就是class的实例对象。如:classcls=Data.class;

②Class和class的区别

  • class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。
  • Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。例如人对应的是Person类,Java类对应的就是Class。Class是Java程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。

2、反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。简而言之,反射就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用就是Class类中方法

获取Class文件对象的方式:

①Object类的getClass()方法。获取字节码文件对象。

Personp = new Person();

Classc = p.getClass();

②数据类型的静态属性class:比第一种方式简单,不用创建对象,也不会调用getClass方法,但是还是要使用具体的类对象和该类的一个静态属性完成。

Classc2 = Person.class;

③Class类中的静态方法forName()方法。注意:要拿带包名的全路径名称:这种方式比较简单,不用创建对象,也不用调用方法,也不需要去调用具体的属性和行为,就能获取到Class对象了。

Classc3 = Class.forName("Person");

一般我们到底使用哪种方法呢?

自己玩:任选一种,第二种较为方便

开发:第三种。为什么呢?因为第三种是一个字符串,而不是一个具体的类名,这样我们就可以把这样的字符串配置到配置文件中。

三种获取Class文件对象的方式演示:



package cn.itcast_01;  
02.  
03./* 
04. *获取Class文件对象的三种方式 
05. */  
06.public class ReflectDemo {  
07.    public static void main(String[] args) throws ClassNotFoundException {  
08.        //第一种  
09.        Person p = new Person();  
10.        Class c = p.getClass();  
11.  
12.        Person p2 = new Person();  
13.        Class c2 = p2.getClass();  
14.  
15.        System.out.println(p == p2);// false  
16.        System.out.println(c == c2);// true  
17.  
18.        //第二种  
19.        Class c3 = Person.class;  
20.        // int.class;  
21.        // String.class;  
22.        System.out.println(c == c3);  
23.  
24.        // 第三种  
25.        // ClassNotFoundException  
26.        Class c4 = Class.forName("cn.itcast_01.Person");  
27.        System.out.println(c == c4);  
28.    }  
29.}  

3、Class类中的常用方法

通过反射获取和使用构造方法和类中成员变量即成员方法

①获取构造方法

  • getConstructor(Class<?>... parameterTypes):返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
  • getDeclaredConstructor(Class<?>... parameterTypes):返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。

②创建对象

  • newInstance():创建此 Class 对象所表示的类的一个新实例。

③获取所有成员

  • getFields():返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
  • getDeclaredFields():返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

④获取单个成员

  • getField(String name):返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
  • getDeclaredField(String name):返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

⑤获取所有方法

  • getMethods():返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
  • getDeclaredMethods(): 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

⑥获取单个方法

  • getMethod(String name,Class<?>... parameterTypes): 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
  • getDeclaredMethod(String name,Class<?>... parameterTypes): 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

方法演示代码如下:


package cn.itcast_02;  
02.  
03.import java.lang.reflect.Constructor;  
04.  
05.import cn.itcast_01.Person;  
06.  
07./* 
08. * 通过反射获取构造方法并使用。 
09. */  
10.public class ReflectDemo {  
11.    public static void main(String[] args) throws Exception {  
12.        // 获取字节码文件对象  
13.        Class<?> c = Class.forName("cn.itcast_01.Person");  
14.  
15.        // 获取构造方法  
16.        // public Constructor[] getConstructors():所有公共构造方法  
17.        // public Constructor[] getDeclaredConstructors():所有构造方法  
18.        Constructor<?> [] cons = c.getDeclaredConstructors();  
19.        for (Constructor<?> con : cons) {  
20.            System.out.println(con);  
21.        }  
22.  
23.        // 获取单个构造方法  
24.        // public Constructor<T> getConstructor(Class<?>... parameterTypes)  
25.        // 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象  
26.        Constructor<?> con = c.getConstructor();// 返回的是构造方法对象  
27.  
28.        Person p = new Person();  
29.        System.out.println(p);  
30.        // public T newInstance(Object... initargs)  
31.        // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,  
32.        //并用指定的初始化参数初始化该实例。  
33.        Object obj = con.newInstance();  
34.        System.out.println(obj);  
35.  
36.        Person p1 = (Person) obj;  
37.        p1.show();  
38.    }  
39.}  

4、Constructor<T>类

①概述:当指定的类中没有空参数构造函数时,或者创建的类对象需要通过指定的构造函数进行初始化,这时候就不能使用Class类中的newInstance方法。这时候我们就需要通过其它的方法来实现了。
②Constructor代表的是某个类的一个构造方法。提供关于类的单个构造方法的信息以及对它的访问权限。
③获取构造方法

  • 获取所有的构造方法:Constructor[] cons = Class.forName(“cn.itheima.Person”).getConstructors();
  • 获取单个构造方法:Constructor con=Person.class.getConstructor(String.class,int.class);

④创建实例对象

  • 反射方式:Person p= (Person)con.newInstance(“lisi”,30);
  • 通常方式:Person p = new Person(“lisi”,30);

注意:创建实例时newInstance方法中的参数列表必须与获取Constructor的方法getConstructor方法中的参数列表一致。

5、Field类

①Field代表的是某个类的某个成员变量。
②方法:

  • Field getField(String s);只能获取公有和父类中公有
  • Field getDeclaredField(String s);获取该类中任意成员变量,包括私有
  • setAccessible(ture);如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
  • set(Object obj, Object value);将指定对象变量上此Field对象表示的字段设置为指定的新值。
  • Object get(Object obj);返回指定对象上Field表示的字段的值。



代码演示如下:

package cn.itcast_03;  
02.  
03.import java.lang.reflect.Constructor;  
04.import java.lang.reflect.Field;  
05.  
06./* 
07. * 通过发生获取成员变量并使用 
08. */  
09.public class ReflectDemo {  
10.    public static void main(String[] args) throws Exception {  
11.        // 获取字节码文件对象  
12.        Class<?> c = Class.forName("cn.itcast_01.Person");  
13.  
14.        // 获取所有的成员变量  
15.        // Field[] fields = c.getFields();  
16.        // Field[] fields = c.getDeclaredFields();  
17.        // for (Field field : fields) {  
18.        // System.out.println(field);  
19.        // }  
20.  
21.        /* 
22.         * Person p = new Person(); p.address = "北京"; System.out.println(p); 
23.         */  
24.  
25.        // 通过无参构造方法创建对象  
26.        Constructor<?> con = c.getConstructor();  
27.        Object obj = con.newInstance();  
28.        System.out.println(obj);  
29.  
30.        // 获取单个的成员变量  
31.        // 获取address并对其赋值  
32.        Field addressField = c.getField("address");  
33.        // public void set(Object obj,Object value)  
34.        // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。  
35.        addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"  
36.        System.out.println(obj);  
37.  
38.        // 获取name并对其赋值  
39.        // NoSuchFieldException  
40.        Field nameField = c.getDeclaredField("name");  
41.        // IllegalAccessException  
42.        nameField.setAccessible(true);  
43.        nameField.set(obj, "林青霞");  
44.        System.out.println(obj);  
45.  
46.        // 获取age并对其赋值  
47.        Field ageField = c.getDeclaredField("age");  
48.        ageField.setAccessible(true);  
49.        ageField.set(obj, 27);  
50.        System.out.println(obj);  
51.    }  
52.}  

6、Method类

①概述:Method类代表类中的一个成员方法,调用某个对象身上的方法,要先得到方法,再针对某个对象调用。
②举一个例子:获得String类的charAt方法。
Method methodCharAt=Class.forName("java.lang.String").getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str,1));//调用str对象中charAt(1)
③调用方法

  • 通常方式:System.out.println(str.charAt(1));
  • 反射方式:System.out.println(charAt.invoke(str,1));//str是一个对象,这里str可以是null,说明invoke()方法是一个静态方法。

④实例应用:用反射方式执行某个类中的main方法
a、目的:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的Main方法。
b、问题:启动java程序的main方法的参数是一个字符串数组, 即public static void main(String[]args),通过反射方式来调用这个main方法时,按jdk1.5的语法,整个数组是一个参数,而jdk1.4的语法,数组的每个元素对应一个参数,当做把一个字符串数组作为参数传递给invoke方法如何处理(注意兼容)。所以,在给main方法传递参数时,不能使用代码mainMthod.invoke(null,newString[]{“xxxx”}),javac只把它当做JDK1.4的语法进行理解,。而不能把它当做JDK1.5的语法解释,因此,会出现参数类型不对的问题。
c、解决办法:

  • 方法一:mainMethod.invoke(null,newObject[]{new String[]{xxxx}});
  • 方法二:mainMethod.invoke)((Object)newString[]{"xxxx"});编译器会做特殊处理,编译时不把参数当做数组看待,也就不会数组达三成若干参数

实例一:Method方法演示


package cn.itcast_04;  
02.  
03.import java.lang.reflect.Constructor;  
04.import java.lang.reflect.Method;  
05.  
06.public class ReflectDemo {  
07.    public static void main(String[] args) throws Exception {  
08.        // 获取字节码文件对象  
09.        Class<?> c = Class.forName("cn.itcast_01.Person");  
10.  
11.        // 获取所有的方法  
12.        // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法  
13.        // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法  
14.        // for (Method method : methods) {  
15.        // System.out.println(method);  
16.        // }  
17.  
18.        Constructor<?> con = c.getConstructor();  
19.        Object obj = con.newInstance();  
20.  
21.        /* 
22.         * Person p = new Person(); p.show(); 
23.         */  
24.  
25.        // 获取单个方法并使用  
26.        // public void show()  
27.        // public Method getMethod(String name,Class<?>... parameterTypes)  
28.        // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型  
29.        Method m1 = c.getMethod("show");  
30.        // obj.m1(); // 错误  
31.        // public Object invoke(Object obj,Object... args)  
32.        // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数  
33.        m1.invoke(obj); // 调用obj对象的m1方法  
34.  
35.        System.out.println("----------");  
36.        // public void method(String s)  
37.        Method m2 = c.getMethod("method", String.class);  
38.        m2.invoke(obj, "hello");  
39.        System.out.println("----------");  
40.  
41.        // public String getString(String s, int i)  
42.        Method m3 = c.getMethod("getString", String.class, int.class);  
43.        Object objString = m3.invoke(obj, "hello", 100);  
44.        System.out.println(objString);  
45.        // String s = (String)m3.invoke(obj, "hello",100);  
46.        // System.out.println(s);  
47.        System.out.println("----------");  
48.  
49.        // private void function()  
50.        Method m4 = c.getDeclaredMethod("function");  
51.        m4.setAccessible(true);  
52.        m4.invoke(obj);  
53.    }  
54.}  

实例二: 写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。

package cn.itheima;  
02.//定义一个测试类  
03.class Test{  
04.    public static void main(String[] args){  
05.        for(String arg : args){  
06.            System.out.println(arg);  
07.        }  
08.    }  
09.}  
10.//用反射方式根据用户提供的类名,去执行该类中的main方法。  
11.import java.lang.reflect.Method;  
12.  
13.public class PerformedMain{  
14.  
15.    public static void main(String[] args) throws Exception {  
16.        //普通方式  
17.        Test.main(new String[]{"123","456","789"});  
18.        System.out.println("-----------------------------");  
19.                  
20.        //反射方式  
21.        String className=args[0];  
22.        Class clazz=Class.forName(className);  
23.                  
24.        Method methodMain=clazz.getMethod("main",String[].class);  
25.        //方式一:强制转换为超类Object,不用拆包  
26.        methodMain.invoke(null, (Object)new String[]{"123","456","789"});  
27.        //方式二:将数组打包,编译器拆包后就是一个String[]类型的整体   
28.        methodMain.invoke(null, new Object[]{new String[]{"123","456","789"}});  
29.    }  

三、数组的反射

①具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
②代表数组的Class实例对象的getSuperClass()方法,返回的父类为Object类对应的Class
③基本类型的一维数组可以被当做Object类型使用,不能作为Object[]类型使用,不能当做Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类使用
④ 注意区别 Array.asList()方法处理int[]和String[]时的差异
⑤ Array工具类用于完成对数组的反射操作

  • Array.getLength(Object obj);获取数组的长度
  •  Array.get(Object obj,int x);获取数组中的元素

     四.反射的重要应用

1.通过反射运行配置文件的内容


public class Demo {  
02.    public static void main(String[] args) throws Exception{  
03.          
04.        /* 
05.        //获取一个class类对象,使用三种方法中那一中,class类中静态方法 
06.        Class aclass =Class.forName("cn.itcast.Test反射读取配置文件.line2"); 
07.        //由获得Class对象再得到一个该类的一个对象 
08.        Object obj=aclass.getConstructor().newInstance(); 
09.        //得到的该类的一个成员方法 
10.        Method m=aclass.getMethod("move", int.class); 
11.        m.invoke(obj, 20); 
12.        */  
13.          
14.        //定义一个class类对象  
15.        Class aclass=Class.forName(getvalue("classname"));  
16.        //通过反射,并调用构造方法,创建一个该类的对象  
17.        Object obj=aclass.getConstructor(String.class).newInstance("好方法");  
18.        //通过反射调用其成员方法  
19.        aclass.getMethod(getvalue("methodname"), int.class).invoke(obj, 50);          
20.    }  
21.    //通过定义一个方法来获取几种东西  
22.    public static String getvalue(String str)throws IOException{  
23.        //定义一个properties集合map集合,以便于读写文件  
24.        Properties pro=new Properties();  
25.        //定义一个输入流  
26.        FileReader filein=new FileReader(new File("pro.properties"));  
27.        //读取文件中内容到集合中  
28.        pro.load(filein);  
29.        //关闭资源  
30.        filein.close();       
31.        return pro.getProperty(str);  
32.    }  
33.}  
34.public class line2 {  
35.    private String name;  
36.    public line2(String name){  
37.        this.name =name;  
38.    }     
39.    public void move(int n){  
40.        System.out.println("名字是:"+name+"小伙的年龄是"+n);  
41.    }  
42.}  

2.通过泛型越过泛型检查

泛型只是在编译期间有作用,可以通过泛型直接加载其class,往声明泛型的集合添加东西

public class Demo {  
02.    public static void main(String[] args) throws Exception  {  
03.        //定义一个集合  
04.        ArrayList<Integer> list=new ArrayList<>();  
05.        list.add(10);  
06.        //使用反射创建此类的class对象,调用其方法  
07.        Class aclass=ArrayList.class;//list.getclass();  
08.        //获取其方法的对象,使用的参数为object.class,通用的类型  
09.        Method m=aclass.getMethod("add", Object.class);  
10.        m.invoke(list, "nihaoma ");  
11.        System.out.println(list);  
12.    }  
13.}  


3.通过泛型设置某个对象的某个属性为指定值

public class Demo {  
02.    public static void main(String[] args) throws Exception {  
03.        Cat c=new Cat();  
04.        setValue(c,"name","bosimao");  
05.        setValue(c, "age", 2);  
06.        System.out.println("年龄:"+c.getAge()+"名字:"+c.getName());  
07.    }  
08.  
09.  
10.    private static void setValue(Object obj, String fieldName, Object value) throws Exception {  
11.        Class aclass=obj.getClass();  
12.        Field field=aclass.getDeclaredField(fieldName);  
13.        //由于是私有属性,需要暴力访问  
14.        field.setAccessible(true);  
15.        field.set( obj, value);  
16.    }     
17.}  
18.public class Cat {  
19.    private String name;  
20.    private int age=0;  
21.      
22.    public String getName(){  
23.        return this.name;  
24.    }  
25.    public int getAge(){  
26.        return this.age;  
27.    }  
28.}  

五.动态代理

1.动态代理的概述

本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。

在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理

2.代理模式:

1).Student类中有一个coding()方法,写程序;
2).测试类中如果需要coding()方法,需要直接实例化一个Student,并调用方法;
如果想在coding()方法的前面或者后面添加一些其他功能,可以不用修改Student类,而为Student类添加
一个"代理类",代理类会调用Student类中的方法。
3).增加了代理类后,测试类不需要直接面对Student,转而使用代理类。代理类中为coding方法添加了新的功能。
实际上就是不直接使用基础类,而是使用第三方代理,并且代理可以添加一些基本功能

public class Demo {//测试类  
02.    public static void main(String[] args) {  
03.        /* 
04.        Student stu = new Student(); 
05.        stu.coding(); 
06.        */  
07.        //使用代理模式  
08.        StudentProxy proxy = new StudentProxy();  
09.        proxy.coding();  
10.    }  
11.}  
12.  
13.  
14.  
15.  
16.public class StudentProxy {//代理类  
17.    public void coding(){  
18.        check();  
19.        new Student().coding();  
20.        zj();  
21.    }  
22.    //先期检查  
23.    public void check(){  
24.        System.out.println("先期检查......");  
25.    }  
26.    //后期总结  
27.    public void zj(){  
28.        System.out.println("后期总结.......");  
29.    }  
30.}  
31.  
32.  
33.  
34.  
35.public class Student {//基础类  
36.    public void coding(){  
37.        System.out.println("做项目,写程序......");  
38.    }  
39.}  

3.动态代理的步骤;

1).自定义一个类,实现InvocationHander接口,并重写接口中的invoke()方法
2).在需要使用代理类的时候,使用Proxy类中的newProxyInstance()方法获取代理类的对象
3).JDK只能为接口做动态代理,所以要为所要代理的类定义一个接口,并去实现接口

public class Demo {//测试类  
02.    public static void main(String[] args) throws Exception {  
03.        //多态的子类对象,使用proxy类中的方法newproxyInstace  
04.          
05.        //Idao idaostu=(Idao) Proxy.newProxyInstance(Class.forName("cn.itcast.Test动态代理.Student").getClassLoader(),   
06.        //                                  Student.class.getInterfaces(),new MyInvocationhander(new Student()));  
07.          
08.        Idao idaostu=(Idao) Proxy.newProxyInstance(Student.class.getClassLoader(),   
09.                                                    Student.class.getInterfaces(),  
10.                                                    new MyInvocationhander(new Student()));  
11.        idaostu.write();//需要使用的方法  
12.    }  
13.}  
14.  
15.  
16.  
17.  
18.public class MyInvocationhander implements InvocationHandler {//实现接口,代理类  
19.      
20.    private Object obj;//定义需要代理的对象  
21.    public MyInvocationhander(Object obj) {  
22.        this.obj=obj;  
23.    }  
24.  
25.  
26.    @Override  
27.    public Object invoke(Object proxy, Method method, Object[] args)  
28.            throws Throwable {  
29.        Object objmethod=method.invoke(obj);  
30.        show();  
31.        return objmethod;  
32.    }  
33.  
34.  
35.    private void show() {  
36.        System.out.println("真是牛叉啊!!");  
37.    }  
38.}  
39.  
40.  
41.public interface Idao {//自己定义接口  
42.    public void write();  
43.}  
44.  
45.  
46.public class Student implements Idao {//自定义类,需要代理的类  
47.          
48.    @Override  
49.    public void write() {  
50.        System.out.println("你好,动态代理!!");  
51.    }  
52.}  


六.枚举

1.枚举概述

一种模式"多例模式":在整个应用程序运行期间,有些类的实例,只允许有固定的几个,这种模式就是"多例模式"
  例如:骰子:需要2个实例;
          扑克:54个实例;        
    现在说的枚举,就是基于"多例模式":  
例如:我们的程序运行期间,需要三个颜色(红\绿\蓝),所以我们使用一个类MyColor来表示颜色。因为我们只需要三个颜色,所以这个类的对象,只能有三个;

public abstract class MyColor3 {//抽象类也是可以定义多例模式  
02.    public static final MyColor3 RED  = new MyColor3("红"){  
03.        @Override  
04.        void show() {  
05.            System.out.println("我是红色的!");  
06.        }};  
07.    public static final MyColor3 GREEN = new MyColor3("绿"){  
08.        @Override  
09.        void show() {  
10.            System.out.println("我是绿色的!");  
11.        }};  
12.    public static final MyColor3 BLUE = new MyColor3("蓝"){  
13.        @Override  
14.        void show() {  
15.            System.out.println("我是蓝色的!");  
16.        }};  
17.    private String colorName;  
18.      
19.    private MyColor3(String colorName){  
20.        this.colorName = colorName;  
21.    }  
22.      
23.    public String toString(){  
24.        return this.colorName;  
25.    }  
26.      
27.    abstract void show();  
28.}  

2.制作枚举步骤:

1).定义枚举:public enum Xxxxx
2).直接定义枚举项。注意:可以有其它成员,但枚举项必须在第一行;
3).枚举中可以包含抽象方法;
4).任何的枚举类,都继承自:Enum类;

public enum MyColor3 {  
02.    RED("红") {  
03.        @Override  
04.        void show() {  
05.            System.out.println("我是红色的!");  
06.        }  
07.    },GREEN("绿") {  
08.        @Override  
09.        void show() {  
10.            System.out.println("我是绿色的!");  
11.        }  
12.    },BLUE("蓝") {  
13.        @Override  
14.        void show() {  
15.            System.out.println("我是蓝色的!");  
16.        }  
17.    };  
18.    private String colorName;  
19.    private MyColor3(String n){  
20.        this.colorName = n;  
21.    }  
22.      
23.    public String getColorName(){  
24.        return this.colorName;  
25.    }  
26.      
27.    abstract void show();  
28.}  

3.枚举类中常用方法,使用枚举对象调用

int compareTo(E o)//比较的是枚举项的索引值,做减法
String name()//枚举项的名字fieldname
int ordinal()//枚举项的索引值
String toString()//枚举对象所对对应的fieldname
<T> T valueOf(Class<T> type,String name)//将一个字符串转换为type类型的对象
values() 
此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便

public class Demo {  
02.    public static void main(String[] args) {  
03.        MyColor3 c1 = MyColor3.RED;  
04.        MyColor3 c2 = MyColor3.BLUE;  
05.          
06.        System.out.println(c2.compareTo(c1));//索引值的减法  
07.        System.out.println("name = " + c2.name());//BLUE  
08.        //int ordinal()  
09.        System.out.println("c2.ordinal() : " + c2.ordinal());  
10.        System.out.println("c1.ordinal() : " + c1.ordinal());  
11.        //String toString()  
12.        System.out.println("c2.toString():" + c2.toString());  
13.        //<T> T valueOf(Class<T> type,String name)  
14.        MyColor3 c3 = c1.valueOf("RED");//将一个字符串转换为MyColor3对象  
15.        MyColor3 c4 = MyColor3.valueOf(MyColor3.class,"BLUE");  
16.          
17.        System.out.println(c3);  
18.        System.out.println(c4);  
19.          
20.        //values()   
21.        MyColor3[] result = c1.values();  
22.        System.out.println("循环遍历:");  
23.        for(MyColor3 c : result){  
24.            System.out.println(c);  
25.        }  
26.    }  
27.}  




                                                              ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据型 在C语言中,变量用于存储数据,数据型用于定义变量的型和范围。C语言支持多种数据型,包括基本数据型(如int、float、char等)和复合数据型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同型数据的复合数据型。结构体由多个成员组成,每个成员可以是不同的数据型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值