1、 静态导入:
import语句可以导入一个类或某个包中所有类。import static语句导入一个类中的某个静态方法或所有静态方法。例如:
import static java.lang.Math.min;
public class StaticImport {
public static void main(String[] args) {
System.out.println(min(90, 50));
System.out.println(min(35, 39));
}
}
上面的代码是没有出错的,import static 静态导入
2、装箱和拆箱:
自动装箱:指开发人员可以把一个基本数据直接赋给对应的包装类。
Integer i = 2;//装箱Integer i = new Integer(“2”);
自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型。
int j = i;//拆箱
典型应用:
List list = new ArrayList();
list.add(1); list.add(2); list(3);//加入的是对象。
3、增强for循环:只适合取数据,要修改数组或集合中的数据,要用传统方式。
代码1:
int arr[] = {1, 2, 3};
for(int num : arr){
System.out.println(num);
}
代码2:
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
for(Object obj : list){
int i = (Integer)obj;
System.out.println(i);
}
看下面如何取出Map中的数据(Map集合是不可以直接迭代的):
1>传统方式1

Map map = new LinkedHashMap();//LinkedHashMap is a raw type
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
Set set = map.keySet();// Returns a Set view of the keys contained in this map
Iterator it = set.iterator();// Returns an iterator over the elements in this set
while (it.hasNext()) {
String key = (String) it.next();
String value = (String) map.get(key);
System.out.println(key + "=" + value);
}
2>传统方式2

Set set = map.entrySet();
Iterator it = set.iterator();
while(it.hasNext()){
Map.Entry entry = (Entry) it.next();
String key = (String)entry.getKey();
String value = (String)entry.getValue();
System.out.println(key + "=" + value);
}
3>增强for循环取map的第一种方式
for(Object obj : map.keySet()){
String key = (String) obj;
String value = (String) map.get(key);
System.out.println(key + "=" + value);
}
4>增强for循环取map的第二种方式
for(Object obj : map.entrySet()){
Map.Entry entry = (Entry) obj;
String key = (String)entry.getKey();
String value = (String)entry.getValue();
System.out.println(key + "=" + value);
}
4、 可变参数:
“…”三个点表示可变参数,可变参数你就把他看成数组 例如:int ...nums
public void test1() {
sum(1, 2, 3, 4, 5, 6);
}
public void sum(int ...nums){
//可变参数你就把他看成数组
int sum = 0;
for(int i : nums){
sum += i;
}
System.out.println(sum);
}
注意的问题:
如果是这样的函数public void sum(int ...nums, int x)操作是不对的,因为sum(1, 2, 3, 4, 5, 6);是可变参数,没有对应的int x参数的值。
这样操作是可以的:public void sum(int x, int …nums); sum(1, 2, 3, 4, 5, 6).
如果定义个数组int attr = {1, 2, 3, 4, 5, 6};然后调用sum(attr);
看下面的代码:
List list = Arrays.asList("1", "2", "3");
System.out.println(list);
String arr[] = {"1", "2", "3", "4"};
list = Arrays.asList(arr);
System.out.println(list);
int nums[] = {1, 2, 3, 5};
list = Arrays.asList(nums);
System.out.println(list);
结果:
[1, 2, 3]
[1, 2, 3, 4]
[[I@1bc82e7]
因为Arrays.asList(nums);传入一个基本类型数组(在java中就是一个特殊的对象),把数组当成一个对象放里面。
如果把int nums[] = {1, 2, 3, 5};把改成Integer nums[] = {1, 2, 3, 5};把(多个)对象数组传入,这样产生的结果是:[1, 2, 3, 5]
6、 枚举:
一些程序在运行时,它需要的数据不能是任意的,而必须是在一定的范围内的值,jdk5以前采用自定义类来解决,jdk5以后可以直接采用枚举解决。
JDK5新增的enum关键字用于定义一个枚举类:一个枚举也可以由构造函数、字段、方法。
使用枚举需要注意:
1>枚举类也是一种特殊形式的Java类。
2>枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
3>与Java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的。
4>枚举类也可以实现接口或继承抽象类。
5>JDK5中扩展了swith语句,它除了可以接受int,byte等外,还可以接收一个枚举类型。
6>若枚举类只有一个枚举值,则可以当作单态设计模式使用。
例如:
//用单态设计模式定义出一个类。
enum A{//class
A;//Object
}
介绍枚举具体用法:
public class Demo4 {
//枚举
@Test
public void test(){
print(Grade.B);
}
public void print(Grade g) { //A B C D E
}
}
//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();
}
*/
//JDK5之后的解决方案。
enum Grade{
A, B, C, D, E;
}
在枚举中添加构造方法:
public class Demo4 {
//枚举
@Test
public void test(){
print(Grade.B);
}
public void print(Grade g) { //A B C D E
System.out.println(g.getValue());
}
}
enum Grade{
A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-50");
private String value;
private Grade(String value){//构造函数
this.value = value;
}
public String getValue(){//对外共享数据
return value;
}
}
带抽象方法的枚举:
enum Grade{
A("100-90"){
public String localValue(){
return "优";
}
}
,
B("89-80"){
public String localValue(){
return "良";
}
}
,
C("79-70"){
public String localValue(){
return "一般";
}
}
,
D("69-60"){
public String localValue(){
return "差";
}
}
,
E("59-50"){
public String localValue(){
return "不及格";
}
};
private String value;
private Grade(String value){
this.value = value;
}
public String getValue(){
return value;
}
public abstract String localValue();// 抽象方法
}
Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。
常用的方法:
name(); ordinal(); valueOf(Class enumClass, String name) ;
value():此方法虽然在JDK文档中查不到,但每个枚举类都具有该方法,它用于遍历枚举的所有枚举值。
7、 反射(用来做框架的):
反射就是加载类,并解剖出类的各个组成部分。
加载类:Java中有一个Class类,用于代表某个类的字节码。
Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName().
forName()方法用于加载某个类的字节码到内存中,并使用class对象进行封装。
其它两种得到class对象的方式:
1>类名.class
2>对象.getClass()
Forexample:
Class clazz1 = Class.forName("/day01/src/com/company/demo1/People"); Class clazz2 = People.class; Class clazz3 = new People().getClass(); |
解剖类:
Class类方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes)
public Method[] getMethods()
public Field[] getFields()
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
public Field getDeclaredField(String name)
具体用法查询API.
小技巧:取得类的全称:在类上右击 -> Copy Qulified Name
实例:
私有的方法和属性能不能被外部访问?
私有的数据不能被外界访问,但是反射可以做到这一点。
Person.java
package com.company.demo1;
public class Person {
public String name = "测试";
public Person() {
System.out.println("person");
}
public Person(String name) {
System.out.println("person:" + name);
}
public Person(String name, int password) {
System.out.println("person" + name + ":" + password);
}
private Person(List list) {
System.out.println("list");
}
}
测试类:
public class Demo3 {
// 反射类的方法:public void aa1()
@Test
public void test1() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", null);
method.invoke(p, null);
}
// 反射类的方法:public void aa1(String name, int password)
@Test
public void test2() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", String.class, int.class);
method.invoke(p, "张飞", 26);
}
// 反射类的方法:public Class[] aa1(String name, int[] password)
@Test
public void test3() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", String.class, int[].class);
Class[] cla = (Class[]) method.invoke(p, "小飞", new int[] { 1, 2, 3 });
System.out.println(cla[0]);
}
// 反射类的方法:private void aa1(InputStream in)
@Test
public void test4() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", InputStream.class);//相同的错误
method.invoke(p, new FileInputStream("d:\\a.txt"));
}
// 反射类的方法:public static void aa1(int num)
@Test
public void test5() throws Exception {
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", int.class);
method.invoke(null, 23);
}
利用Method执行方法:
Method对象提供了如下方法,用于执行它所代表的方法:
public Object invoke(Object obj, Object… args)
练习:使用Method分别执行无参、有参、多个参(带数字和基本数据类型)、静态、私有方法。
研究下面的代码;
Person类
public class Person {
public Person() {
System.out.println("person");
}
public void aa1(){
System.out.println("aa1");
}
public void aa1(String name, int password){
System.out.println(name + ":" + password);
}
public Class[] aa1(String name, int[] password){
return new Class[]{String.class};
}
//该方法测试未通过。
private void aa1(InputStream in){
System.out.println(in);
}
public static void aa1(int num){
System.out.println(num);
}
}
对应的解析类Demo3
public class Demo3 {
// 反射类的方法:public void aa1()
@Test
public void test1() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", null);
method.invoke(p, null);
}
// 反射类的方法:public void aa1(String name, int password)
@Test
public void test2() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", String.class, int.class);
method.invoke(p, "张飞", 26);
}
// 反射类的方法:public Class[] aa1(String name, int[] password)
@Test
public void test3() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", String.class, int[].class);
Class[] cla = (Class[]) method.invoke(p, "小飞", new int[] { 1, 2, 3 });
System.out.println(cla[0]);
}
// 反射类的方法:private void aa1(InputStream in)
@Test
public void test4() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", InputStream.class);//相同的错误
method.invoke(p, new FileInputStream("d:\\a.txt"));
}
// 反射类的方法:public static void aa1(int num)
@Test
public void test5() throws Exception {
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("aa1", int.class);
method.invoke(null, 23);
}
}
特殊反射:
反射类的方法:public static void main(String[] args)
如果用下面的方法来
Class clazz = Class.forName("com.company.demo1.Person");
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, new String[]{"aa", "bb"});
用上面的代码来进行反射,会出现下面的错误:wrong number of arguments.
解决方法1:
method.invoke(null, new Object[]{new String[]{"aa", "bb"}});
解决方法2:
method.invoke(null, (Object)new String[]{"aa", "bb"});
反射类的字段
@Test
public void test() throws Exception {
Person p = new Person();
Class clazz = Class.forName("com.company.demo1.Person");
Field f = clazz.getField("name");
//获取字段的值
Object value = f.get(p);
//获取字段的类型
Class type = f.getType();
if(type.equals(String.class)){
String vname = (String)value;
System.out.println(vname);
}
//设置name的值
f.set(p, "值改变了!");
System.out.println(p.name);
}
反射私有字段和静态字段方法自己编写代码测试。
8、 内省(Introspector):
为什么要学内省?
开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作Java对象的属性。
什么是Java对象的属性和对象属性的读写方法?
属性:属性是通过get和set方法读写的,有多少个属性,是由set或get方法。声明的是字段。
public class Person { //javaBean
private String name; //字段
private String password; //字段
private int age; //字段
//Ab就是该类的一个属性
public String 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;
}
}
该类中共有5个属性,其中有getClass(继承Object)中的class属性
使用内省API操作内省属性:
---------------------------------------------------------------------------------------------------
//得到Bean的属性
BeanInfo info = c.getBeanInfo(Person.class);
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName());
}
---------------------------------------------------------------------------------------------------
上面的代码得到Bean中的所有属性,包括继承Object类的属性。
如果用这段代码代替上面的代码:BeanInfo info = Introspector.getBeanInfo(Person.class, Object.class);这是除去继承Object中的属性。
操作bean指定属性:age
---------------------------------------------------------------------------------------------------
Person p = new Person();
PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
Method method = pd.getWriteMethod();
method.invoke(p, 45);//设置age属性的值
System.out.println(p.getAge());
---------------------------------------------------------------------------------------------------
获取当前操作的属性的类型:
---------------------------------------------------------------------------------------------------
Person p = new Person();
PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
System.out.println(pd.getPropertyType());
---------------------------------------------------------------------------------------------------
课后需要仔细研究的API:
Class Method Field Constructor Instrospector …
9、 泛型:
---------------------------------------------------------------------------------------------------
//自定义泛型的方法
public class Demo1 {
public void testa() {
a("aaa");
}
public <T> T a(T t) {
return t;
}
public <T, E, K> void b(T t, E e, K k){
}
}
---------------------------------------------------------------------------------------------------
<T>声明类型T,使用T t
也可以把泛型声明到类上:public class Demo1 <T, E, K>
静态方法使用泛型用下面的格式:
public static <T> void c(T t){}
面试题:
// 编写一个泛型方法,实现指定位置上的数组元素交换。
// 编写一个泛型方法,接受一个任意数组,并颠倒数组中的所有元素。
|
版权所有 违法必究 若要转载,请说明出处:http://blog.youkuaiyun.com/feilong1105