黑马程序员——Java基础加强—高新技术
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、
<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
一、Eclipse集成开发环境:
Eclipse :2011年11月,IBM投资4000万美元贡献给开源社区。Eclipse 是支持多语言的开发平台。它的价值是为可扩展的集成开发环境提
供了一个开放源码平台,这个平台允许任何人构建与环境和其他工具无缝集成的工具(插件)。Eclipse除了一个小型的运行时核心之外,其
余的都是插件。
IDE:Integrated Development Environment,集成开发环境。
1、在Eclipse 中设置快捷键:
窗口—属性—生成—编辑——键管理
Windows->Preferences->General -> Editors ->Key (Content Assist:内容助理)
2.在Eclipse里面如何调试查看一个变量的值?
(看到甲壳虫图标,就是调试模式)
a.debug as:在Debug透视图进行调试。
b.选中要调试的变量,右击选择Watch。
常用:
F5:调入调试内部
F6:单步调试下一步不进入函数内部。
F7:由函数内部返回到调用处。
F8:直执行到下一个断点。
(4)Ctrl+Pg~ --对于XML文件是切换代
3.设置模板
Windows->Preferences->General -> Editors ->Templates
Syso 会 自动补全System.out.println();
或者 Alt+/ 快捷键
4.Eclipse插件安装方法:
1.拷贝安装。
2.Links安装:eclipse目录下创建links目录>>在links下创建link文件,指定插件路径。path=D:/Plugins- Download/GEF-All-3.1;一个
link文件里面可以添加多个path。
3.Update安装。只要知道插件的更新地址就行。Help>>software update>>find and install>>选择“search for new features to install
”>>next >>“New Renote Site”,添加新的站点后,按eclipse更新向导就可以完成插件安装了。
插件查看:
帮助—关于Eclipse —软件安装
Help >>About Eclipse SDK>>Plug-in Details
二.JDK1.5新特性:
泛型:使用泛型来接收类中操作的引用数据类型 <>
当类中的操作的引用数据类型不确定的时候,可以使用泛型表示.
好处:1.运行时期的问题转换成编译失败,体现在编译时期,方便程序员解决问题,编译不通过,更不可能运行成功。
2.避免强转的麻烦
泛型技术:其实应用在编译时期,是给编译器使用的技术,到了运行时期,泛型就不存在了
泛型的擦除:编辑器检查了泛型的类型正确后,在生成的类文件中是没有泛型的。
泛型的补偿:因为存储的时候,类型已经确定了是同一个类型的元素,所以在运行时,只要获取到该元素的类型,在内部进行一次转换即可。
泛型定义:
1.定义在类上:泛型类定义的泛型在整个类中都有效,泛型类对象明确操作类型后,所有操作类型都固定啦。
2.定义在方法上:静态方法使用泛型只能定义在方法上
3.泛型定义在接口上
方法上:
public static <Q> void function(Q t) {
System.out.println("function:"+t);
}
接口上:
package com.itheima.connection;
public class GenericDemo5 {
/**
* @param args
*/
public static void main(String[] args) {
InterImpl i=new InterImpl<>();
i.show(4);
i.show("haha");
}
}
interface Inter<T>{
void show(T t);
}
class InterImpl<T> implements Inter<T>{
@Override
public void show(T t) {
System.out.print("show:"+t);
}
}
泛型的限定:
上限:?extends E:可以接收E类型或者E的子类型对象。
下限:?super E:可以接收E类型或者E的父类型对象。
可变参数:当一个方法要处理的参数不确定时,则可以设置可变参数
格式:参数类型 ....变量名
public class TestParameter {
public static void main(String[] args) {
System.out.println(add(1,2,3,4,5));
System.out.println(add(1,3));
}
public static int add(int... number){
int sum = 0 ;
for (int i = 0 ; i < number.length ; i++) {
sum += number[i] ;
}
return sum ;
}
}
有多个参数累加 ,要放到最后 pbulc static int add(int x,int ....arg)
2.增强for循环:foreach语句简化了迭代器
格式:for(元素类型、变量名:Connection集合&数组){
}
增强for循环用在迭代器中 参数(声明变量 、迭代内容)
1.Collection 单列集合
ArraList al=new ArryList()
al.add("hao123");
al.add("5858");
for(Object o:al){
String s=(String)o
System.out.println(s);
}
2.使用在Map集合中:
Map集合原则是是不能实现for迭代的,Map没有Iterator 方法。
jdk5中新定义的接口,就一个方法iterator方法,只有实现了Iterable接口的类,才可保证有Iterator方法,
增强for内部还是用迭代器实现的,要将Map转为Set。
Map map = new HashMap();
map.put(1, "a");
map.put(2, "b");
Set entrySet=map.entrySet();//获取Entry 键值对象
Iterator it=entrySet.iterator();
while(it.hasNext()){
Map.Entry en=(Entry)it.next();
Integer key=(Integer)en.getKey(); //分别获取Key 和Value值
String value=(String)en.getValue();
System.out.println(key + "=" + value);
}
使用 for增强:
for(Object obj:map.entrySet()){
Map.Entry entry = (Entry) obj; // obj 依次表示Entry 迭代的内容
} System.out.println(entry.getKey() + "=" + entry.getValue());
3.递归:函数自身调用自身,功能内部又用到了该功能,但是传递的参数不确定。
递归的使用:1.一定要定义递归的条件
2.递归的次数不宜太多,否则会发生栈内存溢出。(栈内存中不断的加载同一个函数)
4.枚举:1.某个类型变量取值只能未若干个固定值,否则会报错,枚举可以再编译时就控制非法值收入。
2.枚举成员只有一个,就可以作为为单例模式实现。
如:定义星期变量只能是周一到周日 1-7
package com.itheima.reflect.demo;
public class EnumTest {
/**
* @param args
*/
public static void main(String[] args) {
WeekDay wd=WeekDay.SUN;
System.out.println(wd);
//打印weekday在WeekDay中的角标
System.out.println(wd.ordinal());
// 获取指定的值 valueOf() 静态方法
System.out.println(wd.valueOf("MON"));
// 获取所有的值
System.out.println(wd.values().length);
}
//创建一个枚举应用 enum类,定义在内部
public enum WeekDay{
SUN,MON,TUE,WED,THI,FRI,SAT
}
}
打印:
SUN
0
MON
7
枚举的构造方法:构造方法私有化private
public enum WeekDay{
SUN,MON,TUE,WED,THI,FRI,SAT(6)
//SUN——FRI初始化调用无参构造方法
public WeekDay(){
}
//SAT(6) 调用的是带参数WeekDay(int day)
public WeekDay(int day){
}
}
枚举带抽象方法:(变量取值固定,定义抽象意义不大
)
交通灯管理系统讲到抽象方法
public enum TrafficLamp{
//new子类的对象,调用父类的构造方法。
RED(40){
public TrafficLamp nextLamp() {
return GREEN ;
}
},
GREEN(60){
public TrafficLamp nextLamp() {
return YELLOW ;
}
},
YELLOW(5){
public TrafficLamp nextLamp() {
return RED ;
}
};
//定义抽象方法:
public abstract TrafficLamp nextLamp() ;
// 定义交通灯的时间,成员变量
private int time ;
private TrafficLamp(int time) {
this.time = time ;
}
}
5.基本数据类型自动拆箱装箱:
方便操作基本类型值,将其封装成对象,定义了属性和行为,丰富数据操作
左边到右边是封装,右转左则是拆箱,装箱与拆箱是一个相互的过程。
基本类型 封装类型
byte Byte
short Short
int Integer
float Float
double Double
public class TestBox {
public static void main(String[] args) {
Integer i = 5 ;
// 自动装箱:将基本数据类型int 5自动封装给一个Integer对象
Integer i = new Integer(5) ;
Integer i = 5; //自动装箱,1.5版本后的写法;
System.out.println(i + 5);
自动拆箱原理:i.intValue()
i=i.intValue()+5 //5是int类型,i是对象封装类型,相加是将i自动转换为int 型 即自动拆箱
Integer a = 13 ;
Integer b = 13 ;
System.out.println(a==b); true a 、b指向的是同一个对象
}
}
举例:Integer x = 1; x = x + 1; 经历了什么过程?装箱——>拆箱——>装箱;
享元模式(flyweight):如果有很多很小的对象,我们会经常用到,用的时候该对象的内部状态都没有变化,那么就可以把他变成一个对象
。那些不同的属性把它变成方法的参数(外部状态),那些相同的属性叫内部状态。
6.反射:
反射就是将一个Java类中各个成分映射成想要的Java类,通过反射来获取类的方法属性等信息。
反射实现步骤:
1.得到Class对象,也就是获得字节码对象(每个类都有对应的字节码对象)
2.实例对象,获得构造函数,属性,方法。
3.访问属性、方法、调用构造函数创建该类对象。
获取Class对象三中方式:
方式一:Class.forName("com.itheima.Person")// 获取指定字符串类名,加载字节码文件
方式二:Class clazz=Person.class ;//明确类 每个数据类型都有静态的.class属性,格式:类名.class 。
方式三:clazz=new Person().getClass();// 对象.getClass()方法,必须有该类对象
反射获取成员方法:getMethod()方法获取
Class clazz=Person.class //获取Class对象
Method m=clazz.getMethod(要获取的方法名,类型.class);
m.invoke()//调用其方法
package com.itheima.reflect.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectDemo4 {
/**
*@throws Exception
* @hutian
*/
//反射获取成员函数,getMethod
public static void main(String[] args) throws Exception {
getMethodDemo3();
getMethodDemo1();
}
public static void getMethodDemo() throws Exception{
// 获取Class对象
Class clazz=Person.class
Method m=clazz.getMethod("paramMethod", String.class,int.class); //获取方法
//invoke()表示调用的意思,需要传入对象和参数
m.invoke("小强", 18);
}
//获取指定Class类中的所有公共函数。。
public static void getMethodDemo1() throws Exception{
// 类名,字符串获取反射信息
Class clazz=Class.forName("com.itheima.bean.Person");
Method[] methods=clazz.getMethods(); //getMethods()获取的是共有的方法
methods=clazz.getDeclaredMethods(); //获取本类中所有方法,包括私有。
for(Method m:methods){
System.out.println(m);
}
}
}
反射构造方法:Constructor 构造器,getConstructor()获取
Class clazz=Class.forName("com.itheima.bean.Person")
//获取带参数的构造方法
Constructor ct= clazz.getConstructor(String.class,int.class);
//对象初始化,使用构造器的newInstance()
Object obj=ct.newInstance("张三",30);
反射成员变量:Field 类代表某个类中的成员变量
//1.获取Class对象
Class clazz=Class.forName("com.itheima.bean.Person")
Object obj=clazz.newInstance(); //初始化
//fl 对象存储的是Person类country 属性值和它所属的对象
Field fl = clazz.getField("country"); //getField()获得的public 共有的成员country(国家)
//暴力反射
Field fl2 = clazz.getDeclaredField("name"); //获取类成员,包括private私有的成员
fl2.setAccessible(true);
案例展示
package com.itheima.reflect.demo;
import java.lang.reflect.Field;
public class ReflectPoint {
/**
* @param args
*/
private int x ;
public int y ;
public String str="bahabak" ;
public String str1="blue" ;
public String str2="balck" ;
public static void main(String[] args) throws Exception {
ReflectPoint rp=new ReflectPoint();
System.out.println("改变前的值:"+rp);
ChangeValue(rp);
System.out.print("改变后的值:"+rp);
}
public ReflectPoint(String str,String str1,String str2){
super();
this.str=str;
this.str1=str1;
this.str2=str2;
}
public ReflectPoint(){
super();
this.x=x;
this.y=y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getstr() {
return str;
}
public void setstr(String str) {
this.str = str;
}
public String getStr1() {
return str1;
}
public void setStr(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
public String toString() {
return str+ ":" + str1+":"+str2 ;
}
public static void ChangeValue(Object obj)throws Exception{
// 获取File对象,先获取Class对象,Filed对象得到成员字段信息
Field[] fl = obj.getClass().getFields() ;
for(Field field:fl){
if(field.getType().equals(String.class)){
if(field.getType()==String.class) {
String old=(String) field.get(obj);
String newString=old.replace('b', 'a');
// 保存修改后的数据
field.set(obj, newString) ;
}
}
}
}
}
打印:
改变前的值:bahabak:blue:balck
改变后的值:aahaaak:alue:aalck
反射作用:实现框架功能
练习: 写一个小框架,该框架的作用则是根据用户的需求设置不同的集合类型如ArrayList、HashSet等,存入数据。
通过配置文件config.properties 来完成集合的选择
package com.itheima.reflect.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.Properties;
public class ReflectTest1 {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 文件存入数据 FileInputStream
FileInputStream fis=new FileInputStream("config.properties");
Properties pt = new Properties() ;
//按照行从读取流中属性键值对元素
pt.load(fis);
//关闭流
fis.close();
String className = pt.getProperty("className") ;
//不同的集合类型如ArrayList、HashSet,Collection 跟接口,反射创建实体
Collection cot=(Collection) Class.forName(className).newInstance();
cot.add("a");
cot.add("haha");
cot.add("helloworld");
cot.add("love you?");
System.out.println(cot.size());
}
}
7.代理与类加载器:
代理类:JVM可以在运行时动态生成类的字节码,这种动态生成的往往被用作代理类。
代理机制:每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,
将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
举例:各人觉得网上购物,通过某宝购物平台,这个购物平台就像是代理。
代理体现:采用工厂模式和配置文件的方式进行管理,实现日志功能
JVM生成的动态类必须实现一个或多个接口,所以,JVM的动态类只能用作具有相同接口的目标类的代理。
实现AOP功能的封装与配置:
Public class BeanFactory{
Properties props=new Properties();
Public BeanFactory(InputStream ips){
Props.load(ips);
}
}public Object getBean(String name){
String className==props.getProperty(name);//根据名字拿类名
Class clazzName=Class.forName(className);
Object bean=clazz.newInstance();
If(bean instanceof ProxyFactoryBean){
Object proxy=null;
ProxyFactoryBean proxyFactoryBean=( ProxyFactoryBean)bean;
Advice advice=(Advice)Class.forName(props.getProperty(name+”.advice”)).newInstance();//系统功能对象
Object target=class.forName(props.getProperty(name+”.advice”)).newInstance();
//目标对象
proxyFactoryBean.setAdvice(advice);
proxyFactory.setTarget(target);
Object proxy=ProxyFactoryBean(bean).getProxy();
}return null;
}
8.类加载器:
顾名思义类加载的工具,将类加载到Java虚拟机中。JVM运行将类的字节码文件加载进来。由加载器名称定位和产生类的字节码依据返
回给JVM。
1.过程:
Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,
并转换成 java.lang.Class类的一个实例。
2.类加载器分类:一般由系统提供,另一类由开发人员自己定义类加载器
引导加载器(Bootstrap) :它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自java.lang.ClassLoader。
扩展加载器(ExtClassLoader 的实例):加载Java扩展库
系统加载器(AppClassLoader的实例):根据Java类ClassPath路径来加载Java类。
自定义加载器:系统已经定义了一些类加载器,为了达到特殊功能,开发者自己定义一些类加载器
自定义的类加载器要继承ClassLoader。
3.类加载器的委托机制: 每个类加载器加载类时,先委托给其上级父类加载器,如果没有,直到BootStrap(祖宗类)加载器,当*父类加载
器没有加载到类时,再尝试自己加载,还加载不到就抛ClassNotFoundException,不会再去找下一级了。
基本上所有的类加载器都是有一个父类加载器,都是java.lang.ClassLoader 类的一个实例
4.相关方法:
getClassLoader() 返回该类的类加载器。返回类型 ClassLoader
getParent() 返回该类加载器的父类加载器。
loadClass(String name) 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。
findClass(String name) 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。
findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。
defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实
例。这个方法被声明为 final的。
resolveClass(Class<?> c) 链接指定的 Java 类。
package com.itheima.proxy;
public class ProxyDemo {
/**
* @param args
*/
public static void main(String[] args) {
ClassLoader loader = ProxyDemo.class.getClassLoader(); //通过 getClassLoader() 方法就可以获取到定义此类加载器
的引用
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent(); //通过递归调用 getParent() 方法来输出全部的父类加载器
}
}
}
打印结果:
sun.misc.Launcher$AppClassLoader@fb56b1
sun.misc.Launcher$ExtClassLoader@f8968f
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、
<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------