一、泛型(Generic)
1.概述
泛型(Generic),即“参数化类型”,是JDK1.5增加的最重要的Java语言特性。在使用泛型之前,集合元素提前之后一定要进行强制类型转换,并且运行时还可能出错。如下面的小例子:
List list = new ArrayList();
list.put(new Integer(3));
Integer i = (Integer) list.get(0);
以上代码使用泛型后如下:
List<Integer> list = new ArrayList<Integer>();
list.put(new Integer(3));
Integer i = list.get(0);
使用泛型可以省去类型强转的麻烦,提高了程序的安全性,将运行前遇到的问题转移到了编译期。泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入。但是,编译器编译带类型说明的集合时会去除掉“类型”信息,目的就是使程序运行效率不受影响。因此,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。
泛型的格式:通过<>来定义要操作的引用数据类型。
通常在集合框架中很常见,只要见到<>就要定义泛型。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
泛型定义中的术语:
如:ArrayList类和ArrayList
1)ArrayList整个称为泛型类型
2)ArrayList中的E称为类型变量或类型参数
3)整个ArrayList称为参数化类型
4)ArrayList中的Integer称为类型参数的实例或实际类型参数
5)ArrayList中的<>称为typeof
6)ArrayList称为原始类型
2、自定义泛型
1)自定义泛型类
若类实例对象中要使用到同一泛型参数,即这些地方引用类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义。
class Worker{
}
class Student{
}
//泛型类
class Utils<T>{
private T obj;
public void setObject(T obj){
this.obj = obj;
}
public T getObject(){
return obj;
}
}
public class GenericClassDemo {
public static void main(String[] args){
Utils<Worker> w = new Utils<Worker>();
w.setObject(new Worker());
Worker ww = w.getObject();
Utils<Student> s = new Utils<Student>();
s.setObject(new Student());
Student st = s.getObject();
}
}
2)自定义泛型方法
泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。
class Demo{
//泛型方法
public <T> void show(T t){
System.out.println("show: "+t);
}
public <Q> void print(Q q){
System.out.println("print: "+q);
}
}
public class GenericMethodDemo {
public static void main(String[] args){
Demo d = new Demo();
d.show(new Integer(4));
d.print("hello world");
}
}
注:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在静态方法上。如: public static void method(T t)
3)自定义泛型接口
泛型接口并不常用,示例如下:
interface Inter<T>{
void show(T t);
}
class InterImpl implements Inter<String>{
public void show(String t){
System.out.println("show: "+t);
}
}
class InterImpl2<T> implements Inter<T>{
public void show(T t){
System.out.println("show2: "+t);
}
}
class GenericInterDemo {
public static void main(String[] args){
InterImpl i = new InterImpl();
i.show("hello");
InterImpl2 ii = new InterImpl2();
ii.show("worldx");
}
}
3、泛型限定
?通配符。
? extends E: 可以接收E类型或者E的子类型(上限)。如Set的addAll方法:addAll(Collection<? extends E> col )
? super E: 可以接收E类型或者E的父类型(下限)。如Collections的fill方法:fill(List<? super T> list, T obj)
import java.util.ArrayList;
import java.util.Iterator;
class Person{
private String name;
Person(String name){
this.name = name;
}
public String getName(){
return name;
}
}
class Teacher extends Person{
Teacher(String name){
super(name);
}
}
public class GenericDemo {
public static void main(String[] args){
ArrayList<Person> p = new ArrayList<Person>();
p.add(new Person("p1"));
p.add(new Person("p2"));
p.add(new Person("p3"));
printColl(p);
ArrayList<Teacher> t = new ArrayList<Teacher>();
t.add(new Teacher("s1"));
t.add(new Teacher("s2"));
t.add(new Teacher("s3"));
printColl(t);
}
//泛型限定
public static void printColl(ArrayList<? extends Person> a1){ //ArrayList<? super Student>
Iterator<? extends Person> it = a1.iterator();
while(it.hasNext())
System.out.println(it.next().getName());
}
}
二、其他对象
1.System类
System类中的字段和方法都是静态的。
常见方法:
1)long currentTimeMillis();获取当前时间的毫秒值,可以通过此方法检测程序的执行时间。
2)Properties getProperties();确定当前的系统属性。Properties集合中存储的都是String类型的键和值。最好使用它自己的存储和取出的方法来完成元素的操作。
3)Windows系统中换行为\r\n两个转义字符,Linux只有一个\n。
4)给属性设置一些属性信息,这些信息是全局的,其他程序都可以使用。如:System.setPeroperty(“myclasspath”,“c:\myclass”);。
import java.util.Properties;
import java.util.Set;
public class SystemDemo {
public static void main(String[] args){
//获取当前时间的毫秒值
long t1 = System.currentTimeMillis();
System.out.println(t1);
//获取系统的属性信息,并存储到Properties集合中
Properties prop = System.getProperties();
Set<String> nameSet = prop.stringPropertyNames();
for (String name: nameSet){
String value = prop.getProperty(name);
System.out.println(name+" = "+value);
}
//获取当前时间的毫秒值
long t2 = System.currentTimeMillis();
System.out.println(t2-t1);
//Windows系统中换行为\r\n两个转义字符
System.out.println("hello\r\nworld");
final String LINE_SEPARATOR = System.getProperty("line.separator");
System.out.println("hi"+LINE_SEPARATOR+"code");
}
}
2.Runtime类
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。应用程序不能创建自己的 Runtime 类实例。
特点:1)没有构造方法摘要,说明该类不可以创建对象。
2)有非静态的方法,说明该类应该提供静态的返回该类对象的方法。
3)只有一个,说明Runtime类使用了单例设计模式。
public class RuntimeDemo {
public static void main(String[] args) throws Exception{
Runtime r = Runtime.getRuntime();
//注意: \b \t \n \f \r \" \' \\ 斜杠不要丢
Process p = r.exec("editPlus.exe C:\\D\\my work\\software");
Thread.sleep(5000);
p.destroy();
}
}
3.Math类
import java.util.Random;
public class TestMath {
public static void main(String[] args){
double d1 = Math.ceil(12.56); //不小于它的整数
double d2 = Math.floor(12.56); //不大于它的整数
double d3 = Math.round(12.56); //四舍五入
System.out.println(d1); //13.0
System.out.println(d2); //12.0
System.out.println(d3); //13.0
double d4 = Math.pow(10, 2); //10的2次方
System.out.println(d4); //100.0
for(int i = 0; i < 5; i++){
//生成0.0——10.0的伪随机数
double d5 = Math.ceil(Math.random()*10);
System.out.println("d5 = "+d5);
}
//生产1.0——7.0的伪随机数
Random r = new Random();
for(int i = 0; i < 5; i++){
double d6 = (int)(r.nextDouble()*6+1);
System.out.println("d6 = "+d6);
}
}
}
3.日期类
1)Date类和DateFormat类
常用操作:
1)日期对象和毫秒值之间的转换
毫秒值–>日期对象:
a.通过Date对象的构造方法 new Date(timeMillis);
b.通过setTime设置。
日期对象–>毫秒值:getTime方法。
2)对日期对象进行格式化
日期对象–>日期格式的字符串:DateFormat类中的format方法。
日期格式的字符串–>日期对象:DateFormat类中的prase方法。
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws Exception{
long time = System.currentTimeMillis();
System.out.println(time);
//将当前日期和时间封装成Date对象
Date date1 = new Date();
System.out.println(date1);
//将指定毫秒值封装成Date对象
Date date2 = new Date(1405244787235l);
System.out.println(date2);
//日期对象-->日期格式的字符串
//获取日期格式对象,具备着默认的风格。也可以指定为FULL、LONG风格。
Date date = new Date();
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
String str_date1 = df.format(date);
System.out.println(str_date1);
df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG);
String str_date2 = df.format(date);
System.out.println(str_date2);
//自定义日期格式
df = new SimpleDateFormat("yyyy-MM-dd");
String str_date3 = df.format(date);
System.out.println(str_date3);
//日期格式的字符串-->日期对象
String str_date5 = "2015年8月28日";
String str_date6 = "2015--8--28";
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
Date date5 = dateFormat.parse(str_date5);
System.out.println(date5);
dateFormat = new SimpleDateFormat("yyyy--MM--dd");
Date date6 = dateFormat.parse(str_date6);
System.out.println(date6);
}
}
/*
* 实例: “2012-5-9”到"2015-8-28"中间有多少天?
*/
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CalculateDays {
public static void main(String[] args) throws Exception{
String str_date1 = "2012-5-9";
String str_date2 = "2015-8-28";
test(str_date1, str_date2);
}
public static void test(String str_date1, String str_date2) throws Exception{
DateFormat dateFormat = DateFormat.getDateInstance();
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = dateFormat.parse(str_date1);
Date date2 = dateFormat.parse(str_date2);
long time1 = date1.getTime();
long time2 = date2.getTime();
long time = Math.abs(time2 - time1);
System.out.println(time);
int day = getDay(time);
System.out.println(day);
}
private static int getDay(long time){
int day = (int)(time/1000/60/60/24);
return day;
}
}
2)Calendar类
Calendar 类是一个抽象类,它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args){
Calendar c = Calendar.getInstance();
showDate(c);
}
public static void showDate(Calendar c){
int year = c.get(Calendar.YEAR);
int month = c.getMaximum(Calendar.MONTH)+1;
int day = c.get(Calendar.DAY_OF_MONTH);
int week = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year+"年"+month+"月"+day+"日"+getWeek(week));
}
public static String getWeek(int i){
String[] weeks = {"", "星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
return weeks[i];
}
}
/*
* 打印某年2月有多少天
*/
import java.util.Calendar;
public class CalendarTest {
public static void main(String[] args){
int year = 2014;
showDays(year);
}
public static void showDays(int year){
Calendar c = Calendar.getInstance();
//将日期设置为3月1日,然后减一天,打印出2月份最后一天的日期,即可知2月多少天
c.set(year,2,1);
c.add(Calendar.DAY_OF_MONTH,-1);
showDate(c);
}
public static void showDate(Calendar c){
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH)+1;
int day = c.get(Calendar.DAY_OF_MONTH);
int week = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year+"年"+month+"月"+day+"日"+getWeek(week));
}
public static String getWeek(int i){
String[] weeks = {"", "星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
return weeks[i];
}
}