• 006-jdk1.5版本新特性


    一、Java SE 5.0 (1.5.0)

    名称:Tiger(老虎)

    发布日期:2004-09-30

    新特性:

    1.1、静态导入

    定义:静态导入用于简化程序对类静态属性和方法的调用。

    语法:

    import static 包名.类名.静态属性|静态方法|*

    示例:

    import static java.lang.System.out;
    import static java.lang.Math.*;

    这样导入后可以在类中直接使用导入的静态属性和静态方法。

    1.2、自动装箱/拆箱

    自动装箱:可以把一个基本数据类型直接赋给对应的包装类。

    Integer i = 1; // 装箱:实际上,是运行时jvm将基本数据类型包装为对应的类对象,再进行赋值

    自动拆箱:可以把一个包装类对象直接赋给对应的基本数据类型。

    int j = i; // 拆箱(i是上述例子中的一个对象)

    1.3、增强for循环

    增强for循环只能用在数组或实现Iterable接口的集合类上。

            int arr[] = {1, 2, 3};
            for (int num : arr) {
                System.out.println(num);
            }

    注意:增强for只适合取数据,要修改数组或集合中的数据,只能要传统的for方式。

    1.4、可变参数

        @Test
        public void testSum() {
            sum(1, 2, 3, 4);
            sum(1, 2, 3);
    
            int[] arr = {1, 2, 3, 4};
            sum(arr);
        }
    
        public int sum(int ...nums) { // 可变参数,我们可以将其看成是一个数组
            int total = 0;
            for (int i: nums) {
                total += i;
            }
            System.out.println(total);
            return total;
        }

    1.5、枚举类

      【详细:https://www.cnblogs.com/bjlhx/p/6673001.html

      为什么需要枚举?
        一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。

    /**
     * JDK5以前
     */
    /*
    class Grade {
        private Grade() {}
        public static final Grade A = new Grade();
        public static final Grade B = new Grade();
        public static final Grade C = new Grade();
        public static final Grade D = new Grade();
        public static final Grade E = new Grade();
    }*/
    
    /**
     * 枚举
     */
    enum Grade {
        A, B, C, D, E; // 枚举的值
    }

    一个枚举也可以有构造函数、字段和方法。

    /**
     * 枚举
     */
    enum Grade {
        A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-0"); // 枚举的每一个值
    
        private String value; // 封装每个对象对应的分数
        private Grade(String value) {
            this.value = value;
        }
        public String getValue() {
            return this.value;
        }
    }

    带抽象方法的枚举

    /**
     * 枚举
     */
    public class DemoAEnum {
    
        @Test
        public void test() {
            print(AbstractGrade.A);
        }
    
        public void print(AbstractGrade g) { // 限定为 A、B、C、D、E
            System.out.println(g.getValue());
            System.out.println(g.localeValue());
        }
    
    }
    
    /**
     * 带抽象方法的枚举
     */
    enum AbstractGrade {
        A("100-90") { // 这里相当于创建枚举对象,并实现抽象方法
            public String localeValue() {
                return "优";
            }
        },
        B("89-80") {
            public String localeValue() {
                return "良";
            }
        },
        C("79-70") {
            public String localeValue() {
                return "中";
            }
        },
        D("69-60") {
            public String localeValue() {
                return "差";
            }
        },
        E("59-0") {
            public String localeValue() {
                return "不及格";
            }
        }; // 枚举的每一个值
    
        private String value; // 封装每个对象对应的分数
    
        private AbstractGrade(String value) {
            this.value = value;
        }
    
        public String getValue() {
            return this.value;
        }
    
        public abstract String localeValue();
    }

    枚举类具有如下特性:

    1. 枚举类也是一种特殊形式的Java类。
    2. 枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
    3. 与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的。
    4. 枚举类也可以实现接口或继承抽象类。
    5. JDK5中扩展了switch语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。
    6. 若枚举类只有一个枚举值,则可以当作单例设计模式使用。

    Java中声明的枚举类,均是java.lang.Enum类的子类,它继承了Enum类的所有方法。常用方法:name()、ordinal()、valueOf(Class enumClass, String name)、values()(用于遍历枚举的所有枚举值)。其中valueOf和values方法均为静态方法。

         /**
         * 测试枚举的常用方法
         */
        @Test
        public void test2() {
            AbstractGrade g = AbstractGrade.C;
    
            System.out.println(g.name());
            System.out.println(g.ordinal());
    
            String str = "B";
            //g = AbstractGrade.valueOf(str);
            g = AbstractGrade.valueOf(AbstractGrade.class, str);
            System.out.println(g.name());
            System.out.println(g.ordinal());
    
            AbstractGrade[] gs = AbstractGrade.values();
            for (AbstractGrade g2: gs) {
                System.out.println(g2);
            }
        }
    View Code

    1.6、反射

    一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。
    Java中有一个Class类用于代表某一个类的字节码。

    1.6.1、实例化加载类

    1️⃣、利用Object中的getClass,但是必须要有明确的实例化对象后才可以调用【了解】

    java.util.Date date = new Date();
    Class<?> class1 = date.getClass();
    System.out.println("全名:"+class1.getName());
    System.out.println("类名:"+class1.getSimpleName());

    输出

    全名:java.util.Date
    类名:Date
    2️⃣、利用“类.class”取得Class类对象,学习Hibernate、mybatis时使用【知道】

    Class<?> class1 = java.util.Date.class;
    System.out.println("全名:"+class1.getName());
    System.out.println("类名:"+class1.getSimpleName());

    3️⃣、利用Class类的static方法取得【掌握】

    实例化Class类对象: public static Class<?> forName(String className) throws ClassNotFoundException 

    Class<?> class2 = Class.forName("java.util.Date");
    System.out.println("全名:"+class2.getName());
    System.out.println("类名:"+class2.getSimpleName());

    好处:可以直接编写字符串

    1.6.2、Class对象提供的基础方法

    以下方法只适用于获取类中public修饰符修饰的构造函数、方法或成员变量。 

    public Constructor getConstructor(Class<?>... parameterTypes)
    public Method getMethod(String name, Class<?>... parameterTypes)
    public Field getField(String name)

    如果需要获取private的,则使用如下方法:

    public Constructor getDeclaredConstructor(Class... parameterTypes)
    public Method getDeclaredMethod(String name, Class... parameterTypes)
    public Field getDeclaredField(String name)

    这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。解剖出的成员分别使用Constructor、Method、Field对象表示。

    1.6.3、类对象实例化

    Constructor类提供了如下方法,用于创建类的对象: 

    正向:new Class

    反射: public T newInstance() throws InstantiationException, IllegalAccessException

    示例

    //正向
    Date date = new Date();
    System.out.println(date);
    //反射
    Class<?> class1=Class.forName("java.util.Date");
    Date date2 = (Date) class1.newInstance();
    System.out.println(date2);

    反射实例化对象,最终也要调用构造方法进行实例化操作。

    1.6.4、反射调用构造方法 

    示例

    import java.util.List;
    
    public class Person {
    
        public String name = "Joy";
    
        public Person() {
            System.out.println("Person");
        }
    
        public Person(String name) {
            System.out.println("Person name: " + name);
        }
    
        public Person(String name, int password) {
            System.out.println("Person name: " + name + ", Person password: " + password);
        }
    
        private Person(List list) {
            System.out.println("list");
        }
    }

    使用反射获取构造方法

    import org.junit.Test;
    
    import java.lang.reflect.Constructor;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 反射类的构造函数,创建类的对象
     */
    public class Demo {
    
        /**
         * 1、通过反射class对象直接创建对象(根据类的无参构造方法创建)
         */
        @Test
        public void test5() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Person p = (Person) cls.newInstance();
            System.out.println(p.name);
        }
        /**
         * 2、反射构造函数:public Person()
         */
        @Test
        public void test1() throws Exception {
            // 利用反射技术创建类的对象
            Class cls = Class.forName("com.wm103.reflect.Person");
            Constructor c = cls.getConstructor(null);
            Person p = (Person) c.newInstance(null);
            System.out.println(p.name);
        }
    
        /**
         * 3、反射构造函数:public Person(String name)
         */
        @Test
        public void test2() throws Exception {
            // 利用反射技术创建类的对象
            Class cls = Class.forName("com.wm103.reflect.Person");
            Constructor c = cls.getConstructor(String.class);
            Person p = (Person) c.newInstance("Dream Test2");
            System.out.println(p.name);
        }
    
        /**
         * 4、反射构造函数:public Person(String name, int password)
         */
        @Test
        public void test3() throws Exception {
            // 利用反射技术创建类的对象
            Class cls = Class.forName("com.wm103.reflect.Person");
            Constructor c = cls.getConstructor(String.class, int.class);
            Person p = (Person) c.newInstance("Dream Test3", 123456);
            System.out.println(p.name);
        }
    
        /**
         * 5、反射构造函数:private Person(List list)
         */
        @Test
        public void test4() throws Exception {
            // 利用反射技术创建类的对象
            Class cls = Class.forName("com.wm103.reflect.Person");
            Constructor c = cls.getDeclaredConstructor(List.class);
            // 私有构造方法反射:如果一个类的构造方法是私有的,也就是private 修饰的,是不能在外部直接使用new 来创建对象。
            // 这个时候你要是使用正常反射会出错。当然不只是构造方法,其他方法,属性等也同样。
            c.setAccessible(true);
            Person p = (Person) c.newInstance(new ArrayList());
            System.out.println(p.name);
        }
    }

    1.6.5、反射调用普通方法 

    Method对象提供了如下方法,用于执行它所代表的方法【jdk1.5】:

    public Object invoke(Object obj, Object... args)

    jdk1.4

    public Object invoke(Object obj, Object[] args)

    示例

    public class Person {
        public String name = "Joy";
        public Person() {
            System.out.println("Person");
        }
        public void method() {
            System.out.println("Person method");
        }
        public void method(String name, int password) {
            System.out.println("Person method");
            System.out.println("Person name: " + name + ", Person password: " + password);
        }
    
        public Class[] method(String name, int[] password) {
            return new Class[]{String.class};
        }
    
        private void method(String name) {
            System.out.println(name);
        }
    
        public static void setNum(int num) {
            System.out.println(num);
        }
    
        public static void main(String[] args) {
            System.out.println("This is a main method. —— Person");
        }
    }

    使用反射获取普通方法

    import org.junit.Test;
    import java.lang.reflect.Method;
    
    /**
     * 反射类的方法
     */
    public class Demo {
    
        /**
         * 1、反射类的方法:public void method()
         */
        @Test
        public void test1() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Object obj = cls.newInstance();
            Method method = cls.getMethod("method", null); // 反射出方法
            method.invoke(obj, null); // 参数:方法调用的对象,方法传入的参数
        }
    
        /**
         * 2、反射类的方法:public void method(String name, int password)
         */
        @Test
        public void test2() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Object obj = cls.newInstance();
            Method method = cls.getMethod("method", String.class, int.class);
            method.invoke(obj, "DreamBoy", 123456);
        }
    
        /**
         * 3、反射类的方法:public Class[] method(String name, int[] password)
         */
        @Test
        public void test3() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Object obj = cls.newInstance();
            Method method = cls.getMethod("method", String.class, int[].class);
            Class[] clss = (Class[]) method.invoke(obj, "DreamBoy", new int[]{1, 2, 3});
            System.out.println(clss[0]);
        }
    
        /**
         * 4、反射类的方法:private void method(String name)
         */
        @Test
        public void test4() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Object obj = cls.newInstance();
            Method method = cls.getDeclaredMethod("method", String.class);
            method.setAccessible(true);
            method.invoke(obj, "DreamBoy");
        }
    
        /**
         * 5、反射类的方法:public static void setNum(int num)
         */
        @Test
        public void test5() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Method method = cls.getMethod("setNum", int.class);
            method.invoke(null, 123456);
        }
    
        /**
         * 6、反射类的方法:public static void main(String[] args)
         * 注意:反射方法时,调用的方法接收一个数组,这时就需要特别注意了!!!
         */
        @Test
        public void test6() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Method method = cls.getMethod("main", String[].class);
            //method.invoke(null, new Object[]{new String[]{"DreamBoy"}});
            method.invoke(null, (Object) new String[]{"Joy"});
        }
    }

    1.6.6、反射调用字段成员方法 

    示例

    import java.util.List;
    
    public class Person {
    
        public String name = "Joy";
        private int password = 1234;
        private static int age = 18;
    
        public Person() {
            System.out.println("Person");
        }
    }

    使用反射获取成员

    import org.junit.Test;
    
    import java.lang.reflect.Field;
    
    /**
     * 反射字段
     */
    public class Demo4 {
    
        /**
         * 1、反射字段:public String name = "Joy";
         */
        @Test
        public void test1() throws Exception {
            Person p = new Person();
            Class cls = Class.forName("com.reflect.Person");
            Field f = cls.getField("name");
            /*String name = (String) f.get(p);
            System.out.println(name);*/
    
            Object value = f.get(p); // 获取字段的值
            Class type = f.getType(); // 获取反射字段的类型
            System.out.println(type);
            if(type.equals(String.class)) {
                String name = (String) value;
                System.out.println(name);
            }
    
            f.set(p, "Moon"); // 设置字段的值
            System.out.println(p.name);
        }
    
        /**
         * 2、反射字段:private int password;
         */
        @Test
        public void test2() throws Exception {
            Person p = new Person();
            Class cls = Class.forName("com.reflect.Person");
            Field f = cls.getDeclaredField("password");
            f.setAccessible(true); // 暴力反射
            Object value = f.get(p); // 获取字段的值
            Class type = f.getType(); // 获取反射字段的类型
            System.out.println(type);
            if(type.equals(int.class)) {
                int password = (int) value;
                System.out.println(password);
            }
    
            f.set(p, 1234567); // 设置字段的值
            System.out.println(f.get(p));
        }
    
        /**
         * 3、反射字段:private static int age = 18;
         */
        @Test
        public void test3() throws Exception {
            Class cls = Class.forName("com.wm103.reflect.Person");
            Field f = cls.getDeclaredField("age");
            f.setAccessible(true); // 暴力反射
            Object value = f.get(null); // 获取字段的值
            Class type = f.getType(); // 获取反射字段的类型
            System.out.println(type);
            if(type.equals(int.class)) {
                int password = (int) value;
                System.out.println(password);
            }
    
            f.set(null, 23); // 设置字段的值
            System.out.println(f.get(null));
        }
    }

    1.7、内省(Introspector)

      开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

      什么是Java对象的属性和属性的读写方法?

        认为具有getter或setter方法的,称为Java对象的属性。如:这里的Person类具有5个属性,即ab、age、name、password,同时还有从父类Object中继承而来的class属性(因为父类Object中包含getClass方法)。

    /**
     * JavaBean
     */
    public class Person {
        private String name;
        private String password;
        private int age;
    
        public Object getAb() {
            return null;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }

    内省访问JavaBean属性的两种方式:
      通过PropertyDescriptor类操作Bean的属性;
      通过Introspector类获取Bean对象的BeanInfo,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后通过反射机制来调用这些方法。

    示例

    import org.junit.Test;
    
    import java.beans.BeanInfo;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Method;
    
    /**
     * 使用内省API操作Bean的属性
     */
    public class Demo {
    
        /**
         * 1、得到bean的所有属性
         * @throws Exception
         */
        @Test
        public void test1() throws Exception {
            // 将对象的所有属性封装到BeanInfo里面去
            BeanInfo info = Introspector.getBeanInfo(Person.class, Object.class); // 加入Object.class后,将只得到bean自身的属性,不包括从Object继承而来的属性
            PropertyDescriptor[] pds = info.getPropertyDescriptors(); // 获取属性描述器
            for (PropertyDescriptor pd: pds) {
                System.out.println(pd.getName()); // 获取类中的属性名:ab、age、name、password。此外还包含了从Object继承而来的class属性。
            }
        }
    
        /**
         * 2、操作bean的指定属性:age
         * @throws Exception
         */
        @Test
        public void test2() throws Exception {
            Person p = new Person();
            PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
            // 得到属性的写方法,为属性赋值
            Method mSet = pd.getWriteMethod();
            mSet.invoke(p, 18);
    
            System.out.println(p.getAge());
    
            // 获取属性的值
            Method mGet = pd.getReadMethod();
            System.out.println(mGet.invoke(p));
        }
    
        /**
         * 3、获取当前操作的属性的类型
         * @throws Exception
         */
        @Test
        public void test3() throws Exception {
            PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
            Class type = pd.getPropertyType();
            if(type.equals(int.class)) {
                System.out.println("Age is int Type");
            }
        }
    }

    针对Bean操作可以使用BeanUtils

     使用BeanUtils操作Bean的属性,需要我们在工程中导入 beanutils jar包,这里我导入commons-beanutils-1.8.0.jarcommons-logging-1.1.1.jar包。

    public class Person {
        private String name;
        private String password;
        private int age;
        private Date birthday;
    
        public Object getAb() {
            return null;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    }
    View Code

    使用

    import org.apache.commons.beanutils.BeanUtils;
    import org.apache.commons.beanutils.ConversionException;
    import org.apache.commons.beanutils.ConvertUtils;
    import org.apache.commons.beanutils.Converter;
    import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
    import org.junit.Test;
    
    import java.lang.reflect.InvocationTargetException;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 使用beanUtils操作bean的属性(第三方)
     */
    public class Demo1 {
    
        /**
         * 操作bean属性
         * @throws Exception
         */
        @Test
        public void test1() throws Exception {
            Person p = new Person();
            BeanUtils.setProperty(p, "name", "HaHa");
            System.out.println(p.getName());
        }
    
        /**
         * 操作bean属性
         * @throws Exception
         */
        @Test
        public void test2() throws Exception {
            String name = "xiaoxiao";
            String password = "123";
            String age = "23";
    
            Person p = new Person();
            BeanUtils.setProperty(p, "name", name);
            BeanUtils.setProperty(p, "password", password);
            BeanUtils.setProperty(p, "age", age); // 这里BeanUtils将字符串转为int类型后赋值,BeanUtils默认只支持对8种基本数据类型进行转换,无法对复杂类型进行转换。
    
            System.out.println(p.getName() + ' ' + p.getPassword() + ' ' + p.getAge());
        }
    
        /**
         * 注册转换器
         * @throws Exception
         */
        @Test
        public void test3() throws Exception {
            String name = "xiaoxiao";
            String password = "123";
            String age = "23";
            String birthday = "2000-01-01";
    
            // 为了让日期赋到bean的birthday属性上,我们给beanUtils注册一个日期转换器
            ConvertUtils.register(new Converter() {
                @Override
                public Object convert(Class type, Object value) {
                    if(value == null) {
                        return null;
                    }
                    if(!(value instanceof String)) {
                        throw new ConversionException("只支持String类型的转换!");
                    }
                    String str = (String) value;
                    if(str.trim().equals("")) {
                        return null;
                    }
    
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                    try {
                        return df.parse(str);
                    } catch (ParseException e) {
                        throw new RuntimeException(e); // 异常链
                    }
                }
            }, Date.class);
    
            Person p = new Person();
            BeanUtils.setProperty(p, "name", name);
            BeanUtils.setProperty(p, "password", password);
            BeanUtils.setProperty(p, "age", age); // 这里BeanUtils将字符串转为int类型后赋值,BeanUtils默认只支持对8种基本数据类型进行转换,无法对复杂类型进行转换。
            BeanUtils.setProperty(p, "birthday", birthday); // BeanUtils中无法帮我们完成从String到Date的转换,需要我们添加转换器
    
            System.out.println(p.getName() + ' ' + p.getPassword() + ' ' + p.getAge() + ' ' + p.getBirthday());
        }
    
        /**
         * 注册转换器
         * @throws Exception
         */
        @Test
        public void test4() throws Exception {
            String name = "xiaoxiao";
            String password = "123";
            String age = "23";
            String birthday = "2000-01-01";
            //String birthday = ""; // 空字符串转换出异常!
    
            ConvertUtils.register(new DateLocaleConverter(), Date.class); // BeanUtils提供了Date转换器
    
            Person p = new Person();
            BeanUtils.setProperty(p, "name", name);
            BeanUtils.setProperty(p, "password", password);
            BeanUtils.setProperty(p, "age", age); // 这里BeanUtils将字符串转为int类型后赋值,BeanUtils默认只支持对8种基本数据类型进行转换,无法对复杂类型进行转换。
            BeanUtils.setProperty(p, "birthday", birthday); // BeanUtils中无法帮我们完成从String到Date的转换,需要我们添加转换器
    
            System.out.println(p.getName() + ' ' + p.getPassword() + ' ' + p.getAge() + ' ' + p.getBirthday());
        }
    
        @Test
        public void test5() throws InvocationTargetException, IllegalAccessException {
            Map<String, String> map = new HashMap<>();
            map.put("name", "WM");
            map.put("password", "12345");
            map.put("age", "23");
            map.put("birthday", "2000-01-01");
    
            Person bean = new Person();
            ConvertUtils.register(new DateLocaleConverter(), Date.class); // 用Map集合中的值,填充bean的属性
            BeanUtils.populate(bean, map);
            System.out.println(bean.getName() + ' ' + bean.getPassword() + ' ' + bean.getAge() + ' ' + bean.getBirthday());
        }
    }
    View Code

    1.8、泛型

    基本使用

      JDK5以前,对象保存到集合中就会失去其特性,取出时通常要程序员手工进行类型的强制转换,这样不可避免就会引发程序的一些安全性问题。

    ArrayList list = new ArrayList();
    list.add("abc");
    Integer num = (Integer) list.get(0); // 运行时会出错,但编码时发现不了

      JDK5中的泛型允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。

       泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛型的java程序后,生成的class文件中将不再带有泛型信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。

      泛型的基本术语,以ArrayList<E>为例:<>念为typeof 

      1. ArrayList<E>中的E称为类型参数变量;
      2. ArrayList<Integer>中的Integer称为实际类型参数;
      3. 整个称为ArrayList<E>泛型类型;
      4. 整个ArrayList<Integer>称为参数化的类型(Parameterized Type)

    1.8.1、自定义泛型方法

      Java程序中的普通方法、构造方法和静态方法中都可以使用泛型。方法使用泛型前,必须对泛型进行声明,语法:<T>,T可以是任意字幕,但通常必须要大写。<T>通常需放在方法的返回值声明之前。例如:

    public static <T> void doXx(T t);

      注意: 

      • 只有对象类型才能作为泛型方法的实际参数;
      • 在泛型中可以同时有多个类型,例如: 
    public static <K, V> V getValue(K key) { return map.get(key); }

    示例

    /**
     * 自定义带泛型的方法
     */
    public class Demo2 {
    
        public <T> T a(T t) { // 这里的 <T> 表示声明泛型,并作用在方法上
            return t;
        }
    
        public <T, E, K> void b(T t, E e, K k) { // <T, E, K> 声明多个泛型
    
        }
    
        public void test1() {
            a("aaa");
        }
    }

    示例2

    /**
     * 自定义类上的泛型
     */
    public class Demo3<T> { // <T> 声明泛型,并作用于整个类,对于静态成员是无效的
    
        public T a(T t) {
            return t;
        }
    
        public <E, K> void b(T t, E e, K k) {
        }
    
        public static <T> void c(T t) {
        }
    }

    1.8.2、自定义泛型类

      如果一个类多处都要用到同一个泛型,这时可以把泛型定义在类上(即类级别的泛型),语法格式如下:

    public class Demo<T> {
        private T field;
        public void save(T obj) {}
        public T getId(int id) {}
    }

    1.9、注解【元数据】

    参看:https://www.cnblogs.com/bjlhx/p/9135774.html

    1.10、协变返回类型

      在面向对象程序设计中,协变返回类型指的是子类中的成员函数的返回值类型不必严格等同于父类中被重写的成员函数的返回值类型,而可以是更 "狭窄" 的类型。

      即子类覆盖(即重写)基类方法时,返回的类型可以是基类方法返回类型的子类。协变返回类型允许返回更为具体的类型。

    示例

    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    
    class Base
    {
        //子类Derive将重写此方法,将返回类型设置为InputStream的子类
      public InputStream getInput()
      {
          return System.in;
      }
    }
    public  class Derive extends Base
    {
        
        @Override
        public ByteArrayInputStream getInput()
        {
            
            return new ByteArrayInputStream(new byte[1024]);
        }
        public static void main(String[] args)
        {
            Derive d=new Derive();
            System.out.println(d.getInput().getClass());
        }
    }
    /*程序输出:
    class java.io.ByteArrayInputStream
    */

    1.11、StringBuilder类

      引入了StringBuilder类,该类的方法不是同步(synchronized)的,这使得它比StringBuffer更加轻量级和有效。

    1.12、 控制台输入(Console Input)

    Scanner in = new Scanner(System.in);
    System.out.print(prompt);
    int n = in.nextInt();
    double x = in.nextDouble();
    String s = in.nextLine();

    1.13、格式化I/O(Formatted I/O)

    public class TestFormat{
    
        public static void main(String[] args){
            int a = 150000, b = 10;
            float c = 5.0101f, d = 3.14f;
            System.out.printf("%4d %4d%n", a, b);
            System.out.printf("%x %x%n", a, b);
            System.out.printf("%3.2f %1.1f%n", c, d);
            System.out.printf("%1.3e %1.3e%n", c, d*100);
        }
    }

  • 相关阅读:
    "《算法导论》之‘图’":不带权二分图最大匹配(匈牙利算法)
    "C#":MySql批量数量导入
    MySql常用操作语句(2:数据库、表管理以及数据操作)
    MySql常用操作语句(1:启动、连接数据库及用户操作)
    HTML 段落
    HTML 标题
    HTML 属性
    HTML 元素
    HTML 基础
    HTML 编辑器
  • 原文地址:https://www.cnblogs.com/bjlhx/p/9546605.html
Copyright © 2020-2023  润新知