名稱:Tiger(老虎)html
發佈日期:2004-09-30java
新特性:程序員
定義:靜態導入用於簡化程序對類靜態屬性和方法的調用。apache
語法:設計模式
import static 包名.類名.靜態屬性|靜態方法|*
示例:數組
import static java.lang.System.out; import static java.lang.Math.*;
這樣導入後能夠在類中直接使用導入的靜態屬性和靜態方法。安全
自動裝箱:能夠把一個基本數據類型直接賦給對應的包裝類。mybatis
Integer i = 1; // 裝箱:實際上,是運行時jvm將基本數據類型包裝爲對應的類對象,再進行賦值
自動拆箱:能夠把一個包裝類對象直接賦給對應的基本數據類型。框架
int j = i; // 拆箱(i是上述例子中的一個對象)
加強for循環只能用在數組或實現Iterable接口的集合類上。jvm
int arr[] = {1, 2, 3}; for (int num : arr) { System.out.println(num); }
注意:加強for只適合取數據,要修改數組或集合中的數據,只能要傳統的for方式。
@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; }
【詳細: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(); }
枚舉類具備以下特性:
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); } }
一個類有多個組成部分,例如:成員變量,方法,構造方法等。反射就是加載類,並解剖出類的各個組成部分。
Java中有一個Class類用於表明某一個類的字節碼。
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());
好處:能夠直接編寫字符串
如下方法只適用於獲取類中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對象表示。
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);
反射實例化對象,最終也要調用構造方法進行實例化操做。
示例
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 { /** * 一、經過反射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); } /** * 二、反射構造函數: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); } /** * 三、反射構造函數: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); } /** * 四、反射構造函數: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); } /** * 五、反射構造函數: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); } }
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 { /** * 一、反射類的方法: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); // 參數:方法調用的對象,方法傳入的參數 } /** * 二、反射類的方法: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); } /** * 三、反射類的方法: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]); } /** * 四、反射類的方法: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"); } /** * 五、反射類的方法: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); } /** * 六、反射類的方法: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"}); } }
示例
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 { /** * 一、反射字段: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); } /** * 二、反射字段: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)); } /** * 三、反射字段: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)); } }
開發框架時,常常須要使用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 { /** * 一、獲得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屬性。 } } /** * 二、操做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)); } /** * 三、獲取當前操做的屬性的類型 * @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.jar
和commons-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; } }
使用
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()); } }
基本使用
JDK5之前,對象保存到集合中就會失去其特性,取出時一般要程序員手工進行類型的強制轉換,這樣不可避免就會引起程序的一些安全性問題。
ArrayList list = new ArrayList(); list.add("abc"); Integer num = (Integer) list.get(0); // 運行時會出錯,但編碼時發現不了
JDK5中的泛型容許程序員在編寫集合代碼時,就限制集合的處理類型,從而把原來程序運行時可能發生問題,轉變爲編譯時的問題,以此提升程序的可讀性和穩定性(尤爲在大型程序中更爲突出)。
泛型是提供給javac編譯器使用的,它用於限定集合的輸入類型,讓編譯器在源代碼級別上,即擋住向集合中插入非法數據。但編譯器編譯完帶有泛型的java程序後,生成的class文件中將再也不帶有泛型信息,以此使程序運行效率不受到影響,這個過程稱之爲「擦除」。
泛型的基本術語,以ArrayList<E>
爲例:<>
念爲typeof
ArrayList<E>
中的E稱爲類型參數變量;ArrayList<Integer>
中的Integer稱爲實際類型參數;ArrayList<E>
泛型類型;ArrayList<Integer>
稱爲參數化的類型(Parameterized Type) 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) { } }
若是一個類多處都要用到同一個泛型,這時能夠把泛型定義在類上(即類級別的泛型),語法格式以下:
public class Demo<T> { private T field; public void save(T obj) {} public T getId(int id) {} }
參看:https://www.cnblogs.com/bjlhx/p/9135774.html
在面向對象程序設計中,協變返回類型指的是子類中的成員函數的返回值類型沒必要嚴格等同於父類中被重寫的成員函數的返回值類型,而能夠是更 "狹窄" 的類型。
即子類覆蓋(即重寫)基類方法時,返回的類型能夠是基類方法返回類型的子類。協變返回類型容許返回更爲具體的類型。
示例
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 */
引入了StringBuilder類,該類的方法不是同步(synchronized)的,這使得它比StringBuffer更加輕量級和有效。
Scanner in = new Scanner(System.in); System.out.print(prompt); int n = in.nextInt(); double x = in.nextDouble(); String s = in.nextLine();
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); } }
是