黑马程序员_java 基础加强1

------- android培训java培训、期待与您交流! ----------

1、静态导入(JDK1.5新特性)

import语句可以导入一个类或者某个包中的所有类。

import static语句导入一个类中的某个静态方法或者所有静态方法。

注:由于静态导入是JDK1.5版本的新特性,所以在使用时当JDK版本低于1.5时,是使用不了的。只有1.5版本以上才可以使用。

示例:

package com.itheima.day01;

import static java.lang.Math.*;

public class StaticImport {
	public static void main(String[] args) {
		System.out.println(max(3, 6));  //使用了静态导入,此处不用写类名Math。
		System.out.println(abs(3-9));
	}
}


2、可变参数(JDK1.5新特性)

可变参数的特点:

1)、只能出现在参数列表的最后;

2)、...位于变量类型和变量名之间,前后有无空格都可以;

3)、调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,方法体中以数组的形式访问可变参数。

注:可变参数也是JDK1.5新特性。

package com.itheima.day01;

public class VariableParameter {

	public static void main(String[] args) {
		System.out.println(add(2,4));
		System.out.println(add(2,4,6));
		System.out.println(add(3,7,9,5));
	}
	
	public static int add(int a,int... args){
		int sum = a;
		/*for(int i=0; i<args.length; i++){
			sum += args[i];
		}*/
		
		for(int s:args){  //增强for循环;
			sum += s;
		}
		return sum;
	}
}


3、增强for循环(JDK1.5新特性)

格式:for(类型  变量名:集合变量名)  {...}

注意事项:1)、迭代变量必须在()中定义;

2)、集合变量可以是数组或者是实现了Iterator接口的集合类。


4、基本数据类型的自动拆箱与装箱

1)、自动装箱:Integer  num1=3;

2)、自动拆箱:System.out.println(num+12);

package com.itheima.day01;

public class AutoBox {

	public static void main(String[] args) {
		Integer num = 12;  //将num封装成一个Integer对象;
		System.out.println(num+12);  //运算的时候num会自动拆箱成数字进行运算;
		
		String s1 = new String("abc");
		String s2 = "abc";
		System.out.println(s1 == s2); //false;
		System.out.println(s1.equals(s2)); //true;
		
		Integer i1 = 5;
		Integer i2 = 5;
		System.out.println(i1 == i2); //true;
		
		Integer i3 = 130;
		Integer i4 = 130;
		System.out.println(i3 == i4);  //false;
	}
}
以上事例中,i1==i2为true,i3==i4为false。这是为什么呢?

java中,将数值较小的(byte型)的数字在封装时(比较常用的),只会封装一次,放下次再有新的对象时还是使用这个已经封装了的对象。当数值较大(超出byte型范围)的数字封装时(使用的频率较低),每次新建对象都会重新封装成一个新的对象。

这种模式也称为享元模式(flyweight)。如果很多很小的对象它们有很多相同的特性,那么就可以把它们变成一个对象,把它们不同的变成外部的属性,作为方法参数传入。



5、枚举(JDK1.5新特性)

1)、为什么要有枚举?

当要定义一个星期几的变量时,该如何定义了?假设用1~7分别表示星期一到星期天,但是有人会写成int  weekDay = 1;

枚举就是要让某个类型的变量的取值只能为固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开放阶段无法实现这一目标。

2)、定义一个WeekDay的类来模拟枚举功能。

A、私有的构造方法;

B、每个元素分别用一个公有的静态成员变量表示;

C、可以有若干个公有方法或抽象方法,例如提供nextDay的方法必须是抽象方法;采用抽象方法定义nextDay可以将大量的if-else语句转换成一个个独立的类,。

如果想在一个类中编写完各个枚举类和测试调用类,那么就可以将枚举类定义成调用类的内部类。

枚举相当于一个类,其中可以定义构造方法、成员变量、普通方法和抽象方法。枚举元素必须位于枚举体中的最开始部分,枚举元素列表的最后要有分号与其他成员隔开。把枚举中的成员方法或变量等放在枚举元素的前面,编译器会报告错误。


带构造方法的枚举的特点:

1)、构造方法必须定义成私有的;

2)、如果有多个构造方法,该调用哪一个构造方法?

3)、枚举元素MON和MON()的效果一样,都调用默认的构造方法。

枚举只有一个成员时,就可以作为一种单例的实现方式。

示例:

模拟WeekDay1:

package com.itheima.day01;

public abstract class WeekDay1 {
	private WeekDay1(){};
	public final static WeekDay1 SUN = new WeekDay1(){

		public WeekDay1 nextDay() {
			return MON;
		}
	};
	
	public final static WeekDay1 MON = new WeekDay1(){
		public WeekDay1 nextDay() {
			return TUES;
		}};
		
	public final static WeekDay1 TUES = new WeekDay1(){
		public WeekDay1 nextDay() {
			return WED;
		}};
		
	public final static WeekDay1 WED = new WeekDay1(){
		public WeekDay1 nextDay() {
			return THUR;
		}};
		
	public final static WeekDay1 THUR = new WeekDay1(){
		public WeekDay1 nextDay() {
			return FRI;
		}};
		
	public final static WeekDay1 FRI = new WeekDay1(){
		public WeekDay1 nextDay() {
			return SAT;
		}};
		
	public final static WeekDay1 SAT = new WeekDay1(){
		public WeekDay1 nextDay() {
			return SUN;
		}};
	
	public abstract WeekDay1 nextDay();
	
	public String toString(){
		if(this == SUN)
			return "SUN";
		else if(this == MON)
			return "MON";
		else if(this == TUES)
			return "TUES";
		else if(this == WED)
			return "WED";
		else if(this == THUR)
			return "THUR";
		else if(this == FRI)
			return "FRI";
		else 
			return "SAT";
		
	}
		
}
主函数部分:

package com.itheima.day01;

public class EnumTest {

	public static void main(String[] args) {

		/*WeekDay1 weekDay = WeekDay1.FRI;
		System.out.println(weekDay.nextDay());*/
		
		/*WeekDay weekDay1 = WeekDay.SUN;
		System.out.println(weekDay1);
		System.out.println(weekDay1.ordinal());
		System.out.println(WeekDay.valueOf("MON").toString());
		System.out.println(WeekDay.values().length);*/
		
		TrafficLamp trafficLamp = TrafficLamp.RED;
		System.out.println(trafficLamp.nextLamp());
	}
	
	public enum WeekDay{
		SUN(1),MON,TUES,WED,THUR,FRI,SAT;
		private WeekDay(){System.out.println("First");}
		private WeekDay(int day){System.out.println("Second");}
	}
	
	public enum TrafficLamp{
		RED(30) {
			public TrafficLamp nextLamp() {
				return GREEN;
			}
		},
		GREEN(40) {
			public TrafficLamp nextLamp() {
				return YELLO;
			}
		},
		YELLO(5) {
			public TrafficLamp nextLamp() {
				return RED;
			}
		};
		public abstract TrafficLamp nextLamp();
		int time;
		private TrafficLamp(int time){
			this.time = time;
		}
	}
}

6、反射

1)、反射的基石-------Class

Java程序中的各个类属于同一类事物,描述这一类事物的java类名就是Class。

例如:描述人这类事物可以用一个Person类来描述,那么描述众多的java类就可以使用Class了。


对比提问:Person类代表人,它的示例对象就是张三这个具体的人。Class类代表java类,它的实例对象对应什么呢?

Class类的实例对象对应各个类在内存中的字节码。例如Person的字节码,Date类的字节码等。一个类被加载器加载到内存中,占用一片存储空间,所以他们在内存中的内容是不同的。这一个个的空间可以分别用一个个的对象来表示,这些对象显然具有相同的类型,这些类型就是Class类型。

如何获得各个字节码对应的实例对象(Class类型)?  

A、类名.class。 例如:System.class;

B、对象.getClass()。 例如:new  Date().getClass;

C、Class.forName("类名")。 例如:Class.forName("java.util.Date")。

只要在源程序中出现的类型,都有各自的Class实例对象。例如int[] , void.......

2)、反射就是把java类中的各种成分映射到相应的java类中。

例如,一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的java类来表示。表示java类的Class要提供一系列的方法来获取其中的变量,方法,构造方法,修饰符,包等信息。这些信息就用相应类的实例对象来表示,它们是Filed、Method、Constructor、Package等等。


3)、Constructor类

Constructor类代表某个类中的一个构造方法。

一个类中有许多的构造方法,那么该怎么样获得其中的某一个构造方法呢?  

由于每一个构造方法的参数列表都是不同的。那么我们就可以通过参数类型和个数来获取了。例如Class.getMethod(name, Class...args)中的args参数就代表所要获取的那个方法的各个参数的类型列表。

得到某个类中的所有构造方法:Constructor consturctor = Class.forName("java.lang.String").getConstructors();

得到某一个构造方法: Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class)。


4)、Field类

Field表示某个类中的一个成员变量。


5)、Method类

Method类代表某个类中的一个成员方法。

例如:得到类中的某一个方法:Method methodCharAt = Class.forName("java.lang.String").getMehtod("charAt",int.class);

调用方法:通常方式:System.out.println(str.charAt(1));

反射方式:System.out.pritnln(methodCharAt.invoke(str,1));

当Method对象的invoke方法的第一个参数为null时,说明该Method对象对应的是一个静态方法。

package com.itheima.day01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectTest {

	public static void main(String[] args) throws Exception {
	
		String str = "abc";
		Class cls1 = str.getClass();
		Class cls2 = String.class;
		Class cls3 = Class.forName("java.lang.String");
		System.out.println(cls1 == cls2); //true
		System.out.println(cls1 == cls3); //ture
		
		System.out.println(cls1.isPrimitive()); //false
		System.out.println(int.class.isPrimitive()); //ture
		System.out.println(int.class == Integer.class); //false
		System.out.println(int.class == Integer.TYPE); //true Integer加上.TYPE后变为基本类型;
		System.out.println(int[].class.isPrimitive()); //false 数组不是原始类型的;
		System.out.println(int[].class.isArray()); //true
		
		//Constructor类
		//new String(new StringBuffer("abc"));  等效于:
		Constructor constructor = String.class.getConstructor(StringBuffer.class);
		String str1 = (String)constructor.newInstance(new StringBuffer("abc"));
		System.out.println(str1.charAt(1));
		
		//Field类
		FieldDemo();
		
		ReflectPoint rp2 = new ReflectPoint(3,5);
		changeStringValue(rp2);
		System.out.println(rp2);
		
		//Method类
		//str.charAt(1);
		Method methodCharAt = String.class.getMethod("charAt", int.class);
		System.out.println(methodCharAt.invoke(str, 1));
		System.out.println(methodCharAt.invoke(str, new Object[]{1})); //JDK1.4做法;	
		
		//需求:调用另一个类中的main方法
		//TestArgument.main(new String[]{"11","22","33"});
		String startingClassName = args[0];
		Method mainMethod = Class.forName(startingClassName).getMethod("main" ,String[].class);
		System.out.println(mainMethod.invoke(null, (Object)new String[]{"11","22","33"}));
	}
	
	private static void FieldDemo() throws Exception {
		ReflectPoint rp1 = new ReflectPoint(2,6);
		Field fieldY = rp1.getClass().getField("y");
		//FieldY不是对象身上的变量,而是类上的变量,要用它的方法去取某个对象上的值;
		System.out.println(fieldY.get(rp1));
		//使用getDeclaredField方法让私有的x可见;
		Field fieldX = rp1.getClass().getDeclaredField("x");
		//使用setAccessible方法可以强制取到x的值;
		fieldX.setAccessible(true);
		System.out.println(fieldX.get(rp1));
		
	}

	private static void changeStringValue(Object obj) throws Exception {
		Field[] fields = obj.getClass().getFields();
		for(Field field: fields){
			if(field.getType() == String.class){
				String oldValue = (String)field.get(obj);
				String newValue = oldValue.replace('b', 'a');
				field.set(obj,newValue);
			}
		}
		
	}

}
public class TestArgument {
	public static void main(String[] args){
		for(String arg: args){
			System.out.println(arg);
		}
	}
}

ReflectPoint类

package com.itheima.day01;

public class ReflectPoint {
	private int x;
	public int y;
	
	public String str1 = "bubble";
	public String str2 = "basketball";
	public String str3 = "itcast";
	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ReflectPoint other = (ReflectPoint) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	public String toString(){
		return str1+":::"+str2+":::"+str3;
	}
}


6)、数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。 代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class。 基本类型的一维数组可以被当做Object类型使用,但不能当做Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

注意:Arrays.asList()方法处理int[]和String[]时的差异(为了兼容JDK1.5一下版本的原因)。

package com.itheima.day01;

import java.lang.reflect.Array;
import java.util.Arrays;

public class ReflectTest2 {

	public static void main(String[] args) {
		int[] a1 = new int[]{1,2,3};
		int[] a2 = new int[3];
		int[][] a3 = new int[2][2];
		String[] a4 = new String[]{"a","b","c"};
		System.out.println(a1.getClass() == a2.getClass());
		//System.out.println(a1.getClass() == a3.getClass());  //错误;
		//System.out.println(a1.getClass() == a4.getClass());  //错误;
		System.out.println(a1.getClass().getName());  //[I
		System.out.println(a1.getClass().getSuperclass().getName());  //java.lang.Object
		System.out.println(a4.getClass().getSuperclass().getName());  //java.lang.Object
		System.out.println(a3.getClass().getSuperclass().getName());  //java.lang.Object
		
		Object obj = a1;
		Object obj1 = a3;
		Object obj2 = a4;
		//Object[] obj3 = a1; //错误,该数组相当于该数组中装有Object类型的元素,但是a1中的元素为基本数据类型int型,不属于Object对象;
		Object[] obj4 = a3;   //该数组相当于一个数组中装有一维数组元素,数组元素是Object对象;
		Object[] obj5 = a4;   //该数组相当于数组中装有String类型的元素,String类型的元素师Object对象;
		//需求,打印出a1、a4中的元素;
		System.out.println(Arrays.asList(a1));  //打印结果:[[I@dc8569]  不能够打印出a1中的元素,打印的是其哈希值;
		System.out.println(Arrays.asList(a4));  //打印结果:[a, b, c]
		
		
		//通过Array工具类完成对数组的反射操作;
		printObject(a1);  //打印结果:1  2  3
		printObject("abc");  //打印结果:abc

	}

	private static void printObject(Object obj) {
		Class cls = obj.getClass();		
		if(cls.isArray()){
			int len = Array.getLength(obj);
			for(int i=0; i<len; i++){
				System.out.println(Array.get(obj, i));
			}
		}
		else{
			System.out.println(obj);
		}
		
	}

}

7、ArrayList和HashSet的比较以及hashCode的分析

示例:

package com.itheima.day01;
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashSet;

public class ReflectTest3 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//Collection collections = new ArrayList(); //Size为5;
		Collection collections = new HashSet();     //Size为4;由于HashSet不能存入相同的元素,所以pt1只能存进一个;
		ReflectPoint pt1 = new ReflectPoint(2,5);	//当我们覆盖了其HashCode后,pt3和pt4就只能存储一个了,其size也就会变为3;
		ReflectPoint pt2 = new ReflectPoint(3,4);
		ReflectPoint pt3 = new ReflectPoint(6,8);
		ReflectPoint pt4 = new ReflectPoint(6,8);
		
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);
		collections.add(pt4);
		collections.add(pt1);
		
		//pt4.y = 9;  //此时如果修改了pt4中y的值,再删除掉pt4,collections的size为3;也就是说pt4没有删除掉;
		//这是为什么呢?由于修改了y的值,该对象的hashCode也就改变了,即该对象的存储区域改变了,而做删除动作的时候,它还是在原来
		//的那片区域寻找pt4,所以也就找不到了,也就没有做删除掉pt4了;这样如果对象数据多了,也就会造成内存泄露了;
		collections.remove(pt4);  //如果没有修改要的值,直接remove掉pt4,则collections的size为2;
		System.out.println(collections.size());
	}

}

反射的作用:实现框架功能

package com.itheima.day01;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Properties;

public class ReflectTest4 {

	/**
	 * @param args
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) throws Exception {
		
		/*要用完整的路径来获取配置文件的路径,但完整的路径不是硬编码,使用getRealPath()来获取路径;*/
		//InputStream in = new FileInputStream("config.properties");
		
		InputStream in = ReflectTest4.class.getClassLoader().getResourceAsStream("cn/itcast/day01/config.properties");
		Properties props = new Properties();
		props.load(in);
		in.close();
		String className = props.getProperty("className");
		Collection collections = (Collection)Class.forName(className).newInstance();    
		
				
		ReflectPoint pt1 = new ReflectPoint(2,5);	
		ReflectPoint pt2 = new ReflectPoint(3,4);
		ReflectPoint pt3 = new ReflectPoint(6,8);
		ReflectPoint pt4 = new ReflectPoint(6,8);
		
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);
		collections.add(pt4);
		
		System.out.println(collections.size());
	}

}

------- android培训java培训、期待与您交流! ----------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值