黑马程序员_基础加强01

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

1 MyEclipse和Eclipse
1.1)MyEclipse原本是Eclipse的一个小补丁,以前我们安装了Eclipse,为了能用到更多的功能,通常都会安装补丁MyEclipse,那么我们发现每次安装Eclipse都要去另外的安装Eclipse,很麻烦,所以后来厂商就把MyEclipse和Eclipse结合了起来,只要安装了Myeclipse就具备了以上两个功能了.

1.2)MyEclipse和Eclipse都是用java工具编写的,所以启动它们就是在启动java工具javaw.exe,启动时你会在任务管理器上面看到javaw.exe进程,如果MyEclipse或者Eclipse死掉了,可以手动结束javaw.exe进程

1.3) 面试的时候,写包名最好写公司的网址
1.3.1)如百度网址是:www.baidu.com.cn
包名就是:cn.baidu
1.3.2)如果你不知道公司的网址是什么,包名可以写成:cn.interview
1.3.3)类名和变量名,要写单词的全称,因为面试的时候,人家没有那么多时间看你写的是什么

1.4)Eclipse的快捷键配置
General代表这个工作间里的所有工程都按照这样的设置
General-Editors-Keys-Content Assist 内容助理
看到里面绑定了一些快捷键,如果要按照自己的想法去设置,可以点击Remove Binding
然后重新设置快捷键:长按ALT键不放再按/,点击Apply,保存就行了,
如果不行,肯定是其他快捷键也绑定了ALT+/,让它解除绑定就行了
例子:
工作台上键入:syso然后按alt+/就会弹出System.out.println();

1.5)工作台空间workspace和工程project的关系
工作台里面可以有多个工程,有了工作台就可以在里面创建工程

1.6)Perspective透视图和view视图

1.6.1)透视图
透视图由多个视图组成,就是说我们在编写程序的时候,可能要用到一些视图,按照需要不同的透视图里放着不同的视图
1.6.1)视图:视图就是我们通常所说的视图,就是在myeclipse里面的各个小窗口
怎么调出视图:window-show View里面有很多小窗口,如果这里没有选中show View的other可以把里面的视图调出来
1.6.2)注意:设置端点,比如说我们要调试变量x的值,
先在变量和System.out.println的左边双击鼠标左键,然后在页面点击右键,调出透视图:Debug As--java application
进去Debug之后,选中x点右键,选watch,如果要再次调试,点击工具类的顺时针箭头,x就会变为2(走单步)
/*
例子1:设置端点,获取变量x的值
public class StaticImport {
 public static void main(String[]args)
 {
  int x=1;
//在最左边双击两下,设置端点
.  x++;
.  System.out.println(x);
 }

}
*/

1.7)首选参数Preferences
1.7.1)编译用的版本比运行用的版本低,运行可以通过,否则,会出错
window-Preferences-Compiler(编译)右上角可以选择,编译的时候用jdk那个版本,是作用于整个工作台
选中工作台右键-Properties-java Compiler单个工程编译的时候用的jek版本,作用于单个工程

选中工作台右键-Run-Configurations--JRE这里选择单个工程运行时用的jek版本,作用于单个工程
window-Preferences-Installed JREs右上角可以选择,运行的时候的时候用jdk那个版本,是作用于整个工作台

1.8)myeclipse模版
1.8.1)模版创建:window-Preferences-Editor-Templates-new
/*
例子:模版创建
try{
${line_selection}  //line_selection插入的代码
}
finally{
${cursor}          //cursor光标停留的位置
*/
使用:选中要使用模版的代码-点击右键-Surrounding with-选择模版
就行了

1.9)导入工程
步骤:先把工程拷贝到工作台上--File--Import-General--Existing Projects into Workspace
要注意导入后如果导入的文件jdk跟本机的不一样,要新建一个类库


2 要注意面试会出现的问题:
请解释以下的名词:
java ee
ide-->itegrity development environment集成开发环境 
jms 
jmx
jndi
Perspective透视图
IntroSpector内省

3 静态导入
3.1)静态导入的好处
如果我们按照正常的导入方法,然后把这个类导进文件里面了,我们写程序的时候调用方法:类名.方法
如果我们使用静态导入:调用静态方法,就不用在前面写类名了,直接写上面静态方法就行了
3.2)格式:import static java.lang.Math.*;
3.3)注意事项:在myeclipse里,我们导入了一个静态类,但是调用静态方法却报错,很可能是首选参数里面编译版本选择了jdk5.0以下的版本
3.4)
/*
例子:静态类Math方法的调用
*/
import static java.lang.Math.*;
public class StaticImport {
 public static void main(String[]args)
 {
  
  System.out.println(max(3,6));
  System.out.println(abs(3 - 5));
 }
}

4 享元模式flyweight
如果很多的对象都是相同的,那么可以在内存中只定义一个对象,当需要的
时候就进去内存拿这个对象就可以了

5 枚举
5.1)为什么要有枚举?
要定义星期几或性别的变量,该怎么定义呢?假设用1到7分别表示星期一到星期日,但有人可能会写成int weekday=8;
为了限定weekday的取值范围就用到了枚举
5.2)枚举就是要让某个类型的变量的取值只能为若干个固定值的一个,否则,编译器就会报错
枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段实现这一目标
5.3)定义一个Weekday的类来模拟枚举功能
   步骤:私有的构造方法
        每个元素分别用一个公有的静态成员变量表示
        可以有若干个方法或抽象类

注意:要让myeclipse自动产生一个新类,选中类名,点右键,Create class'WeekDay'
/*
例子1:定义一个Weekday的类来模拟枚举功能
*/
package cn.itcast;
public class EnumTest {
 public static void main(String[] args)
 {
  Weekday wd=Weekday.sun;
  System.out.println(wd.getWeekday());
 }
}
定义一个Weekday抽象类
package cn.itcast;
public abstract class Weekday {
 private Weekday(){};
 //匿名内部类复写父类抽象方法
 public static final Weekday sun=new Weekday(){
  public Weekday getWeekday()
  {
   return sun;
  }
 };
 public static final Weekday mon=new Weekday(){
  public Weekday getWeekday()
  {
   return mon;
  }
 };
 
 public abstract Weekday getWeekday();
 
 public String toString()
 {
  return this==sun?"sun":"mon";
 }
}

例子2:在本类中定义枚举
package cn.itcast;
public class EnumTest {
 public static void main(String[] args)
 {
  Weekday1 wd=Weekday1.sun;
  System.out.println(wd.getWeekday());
  
  WeekDay weekDay2=WeekDay.FRI;
  System.out.println(weekDay2);
  System.out.println(weekDay2.name());
  //打印FRI在枚举中的序列号
  System.out.println(weekDay2.ordinal());
  //把"sun"字符串变为枚举对象
  System.out.println(WeekDay.valueOf("SUN"));
  //values得到枚举类的数量,并返回一个数组
  //length得到数组长度
  System.out.println(WeekDay.values().length);
 }
 
 //定义枚举,用到关键字enum
 public enum WeekDay
 {
  SUN,MON,TUE,WED,THI,FRI,SAT;
  private WeekDay()
  { 
   System.out.prtintln("first");
  }
  private WeekDay(int day)
  {
   System.out.prtintln("second"); 
  }
 }
 //定义一个交通灯的枚举例子
 public enum TrafficLamp
 {
  RED(30)
  { //创建TrafficLamp对象,因为它是一个抽象类,所以要用匿名内部类复写抽象方法后才创建对象
   public TrafficLamp nextLamp()
   {
    return GREEN;
   }
  },
  GREEN(45)
  {
   public TrafficLamp nextLamp()
   {
    return YELLOW;
   }
  },
  YELLOW(10)
  {
   public TrafficLamp nextLamp()
   {
    retrun RED;
   }
  };
  private int time;
  private TrafficLamp(int time)
  {
   this.time=time;
  }
  public abstract TrafficLamp nextLamp();
 }
}

5.4)定义枚举要注意的地方:
5.4.1)SUN,MON,TUE,WED,THI,FRI,SAT;这些枚举对象要放在枚举的第一行
5.4.2)SUN,MON,TUE,WED,THI,FRI,SAT;如果这些枚举对象后面还有东西要写的话,后面要加上分号
5.4.3)SUN(1),MON();可以通过这样的方式指定枚举对象创建的时候调用的构造方法,MON()和MON默认调用的都是空参数构造方法

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

5.6)匿名内部类
格式:Weekday sun=new Weekday(){};
在中括号里写东西,一般都是覆盖父类的抽象方法,sun是父类,因为子类没有名字,
而且又定义在父类里面,所以叫做匿名内部类
public static final Weekday sun=new Weekday(){
  public Weekday getWeekday()
  {
   return sun;
  }
 };

6 Class类--反射的基石
6.1)Class类
java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class
对比提问1:
众多的人用一个什么类表示?众多的java类用一个什么类表示?
人-->Person
java类-->Class

对比提问2:Person类代表人,它的对象是张三,李四这样一个个的具体实例,
那么Class类代表java类,它的各个实例对象又是代表什么呢?
对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码等等

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同类的字节码是不同的,所以他们在内存中的内容也不同,这一个个的空间可分别用一个个对象分别表示,而且他们的返回值类型都是一样的:Class

6.2)得到字节码文件对象常见的三种方法
6.2.1)类名.class   例子:System.class;
6.2.1)对象.getClass   例子:new Date().getClass();
6.2.1)Class.forName("类名")  例子:Class.forName("java.util.Date");
forName("类名");得到字节码文件对象,如果内存已经加载过了这个字节码,java虚拟机就直接返回这个字节码文件对象,如果没有就从硬盘先加载到内存,再返回

6.3)注意:只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[] ,void等
6.3.1)int.class==Integer.TYPE
6.3.2)数组类型的Class实例对象:  Class.isArray()
/*
获取字节码文件对象并使用的例子
*/
package cn.itcast;
public class ReflectTest {

 /**
  * @param args
  */
 public static void main(String[] args)throws Exception {
  // TODO Auto-generated method stub
  String str1="abc";
  Class cls1=str1.getClass();
  Class cls2=String.class;
  Class cls3=Class.forName("java.lang.String");
  
  System.out.println(cls1==cls2);
  System.out.println(cls1==cls3);
  //isPrimitive方法是判断类对象是否是基本类型的类对象(byte,char,short,int,long...)
  System.out.println(cls1.isPrimitive());
  System.out.println(int.class.isPrimitive());
  System.out.println(int.class==Integer.class);
  System.out.println(int.class==Integer.TYPE);
  //静态方法isArray是判断字节码文件对象是否是数组类型的字节码文件对象
  System.out.println(int[].class.isArray());
 }

}

7 反射:反射就是把java类中的各种成分映射成相应的java类.
例如:一个java用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包,等等信息也用一个个的java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等也是一个个的类.
表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field,Method,Contructor,Package等等

7.1)Constructor类代表某个类中的一个构造方法
7.1.1)得到某个类所有的构造方法:
例子:Constructor[] constructors=Class.forName("java.lang.String").getConstructors();
7.1.2)得到某一个构造方法:
一个类有多个构造方法,用什么方式可以区分清楚想得到其中那个方法呢?
注意:是根据参数的个数和类型
例子:Constructor constructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class);
7.1.3)创建实例对象:
通常方式:String str=new String(new StringBuffer("abc"));
反射方式:String str=(String)constructor.newInstance(new StringBuffer("abc"));
7.1.4)Class.newInstance()方法
例子:String obj=(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象

8 Field类代表某个类中的一个成员变量
问题:得到的File对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联那个对象呢?所以字段fieldX代表的是x的定义,而不是具体的x变量.

8.1)获取字节码文件对象的成员变量值
/*
例子1:获取字节码文件对象的成员变量值
*/
package cn.itcast;
public class ReflectPoint {
 private int x;
 public int y;
 public ReflectPoint(int x, int y) {
  super();
  this.x = x;
  this.y = y;
 }
 
}

package cn.itcast;

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

public class ReflectTest {

 /**
  * @param args
  */
 public static void main(String[] args){
  
  ReflectPoint pt1=new ReflectPoint(3,5);
  //getField()只能得到可见的变量(不是private)
  Field fieldY=pt1.getClass().getField("y");
  System.out.println(fieldY.get(pt1));
  //因为成员变量x是私有的,所以不能直接获取,getDeclaredField()是获取类中声明的成员变量x,  setAccessible(true)是暴力获取私有的值,这样的方法叫做暴力反射
  Field fieldX=pt1.getClass().getDeclaredField("x");
  fieldX.setAccessible(true);
  System.out.println(fieldX.get(pt1));
  
 }

}

/*
例子2:修改获取到了Field相应的值
*/
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);
   }
 }
 
9 Method类
9.1)得到类中的某一个方法:
Method charAt=Class.forName("java.lang.String").getMethod("charAt",int.class); 
调用用法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(chaAt.invoke(str,1));

9.2)例子:
  Method methodCharAt = String.class.getMethod("charAt",int.class);
  System.out.println(methodCharAt.invoke(str1,1));
  System.out.println(methodCharAt.invoke(str1,new Object[]{2}));

10 用反射方式执行某个类中的main方法
目的:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
问题:启动java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如果为invoke方法传递参数呢?按jek1.5的语法,整个数组是一个参数,而按jdk1.4的语法数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac到底会按照那种语法进行处理呢?jek1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成若干个单独的参数,所以,在给main方法传递参数时,不能使用
mainMethod.invoke(null,new String[]{"xxx","xx"}),javc只把它当作jdk1.4的语法进行理解,因此会出现参数类型不对的问题.

解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx","xx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx","xx"}); 编译器会做特殊处理,编译时不会把参数当作数组看待,也就不会把数组打散成若干个参数了

例子:
package cn.itcast;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectTest {

 /**
  * @param args
  */
 public static void main(String[] args)throws Exception {
  
  String startingClassName = args[0];
  Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
  mainMethod.invoke(null,(Object)new String[]{"111","222","333"});
    
 }

 
}

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

11 数组的反射
11.1)具有相同维数和元素类型属于同一个类型,即具有相同的Class实例对象
11.2)代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
int[] a1=new int[3];
int[] a2=new int[4];
int[][] a3=new int[2][3];
String[] a4=new String[3];
a1.getClass().getSuperclass().getName();//java.lang.object
a2.getClass().getSuperclass().getName();//java.lang.object

Object[] aobj3=a1;//这是错的,因为a1里面都是基本数据类型,而Object不包括基本数据类型

例子:
private static void printObj(Object obj) {
  Class clazz=obj.getClass();
  if(clazz.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);
  }
  
 }

11.3)内存泄漏:对象不用了,把它删掉,以为删除成功了,但是实际上是没有删掉,这就叫做内存泄漏

面试题:hashCode()方法的作用:
向HashSet集合存储对象的时候,存储第一个对象,集合内部先算出对象的哈希值,然后根据哈希值放到指定的区域,然后再存储另一个对象的时候,集合又算出这个对象的哈希值,然后根据哈希值找到相应的区域,再找出该存储区域里面的每个元素与该对象进行equals比较,然后得出这个对象在集合里是否存在,这样就不用跟集合里的每一个元素都进行比较了,提高了效率.

注意:类中参与运算得出哈希值的成员,都不能改变,否则可能会出现内存泄漏
例子:
class Test
{
 int x;
 int y;
 Test(int x,int y)
 {
  this.x=x;
  this.y=y;
 }
 public hashCode()
 {
  return x*y;
 }
 public boolean equals(Object obj)
 {
  return this.x==obj.x && this.y==obj.y;
 }
}
HashSet hs=new HashSet();
Test t1=new Test(3,5);
Test t2=new Test(6,8);
hs.add(t1);
hs.add(t2);
假如x是参与了得出哈希值的运行的,然后x被改变了
t1.x=10;
hs.remove(t1);//假设t1对象进来的时候根据哈希值,是存储在b这块区域的,但是现在x变化了,哈希值也变了,删除的时候去c这块区域找,没有找到,所以就没有删除成功,而你又以为删除成功了,所以可能会造成内存泄漏现象

12 反射的作用-->实现框架功能
12.1)我做房子卖给用户住,用户自己安装门窗和空调,我做的房子就是框架,用户需要使用我的框架,把门窗插入进我提供的框架中,框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类
12.2)框架要解决的核心问题
我在写框架(房子)的时候,你这个用户可能还在上小学,还不会写程序呢?我写的框架程序怎样能调用到你以后写的类(门窗)呢?

/*
例子:框架的简单例子,由用户输入类名,然后框架调用这个类执行动作
注意:以下例子中,如果ReflectPoint类没有覆盖hashCode()方法的话,输出结果是4,pt1和pt3两个相同的对象会存进HashSet集合中去,因为HashSet集合先得到元素的哈希值,然后在哈希值相应的区域调用equals方法,比较两个元素是否相等,
现在,如果你没有覆盖hashCode()方法,那么两个对象的地址值肯定是不一样的,则哈希值也不一样,那么当你存入pt3对象时,集合算到pt3对象的哈希值,在相应的区域,那么就去相应的区域,调用equals方法,拿这个区域里的元素逐一比较,因为pt1跟pt3哈希值不一样,所以pt1不在pt3比较的区域里,所以pt3被存进来了
*/
package cn.itcast;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;

package cn.itcast;
public class ReflectPoint {
 private int x;
 public int y;
 public String str1="ball";
 public String Str2="basketball";
 public String str3="itcast";
 public ReflectPoint(int x, int y) {
  super();
  this.x = x;
  this.y = y;
 }
 @Override
 public String toString() {
  return "ReflectPoint [Str2=" + Str2 + ", str1=" + str1 + ", str3="
    + str3 + ", x=" + x + ", 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 class ReflectTest2 {
 public static void main(String[]args)throws Exception
 {
  Properties prop=new Properties();
  /*
  这是得到配置文件的第一种方法:因为FileInputStream("config.properties")是  读取当前目录的文件,如果当前目录没有这个文件
  那么这个就会报错
  InputStream ins=new FileInputStream("config.properties");
  
  
  这是得到配置文件的第二种方法:先得到类的加载器getClassLoader  (),getResourceAsStream是加载classPath目录下的文件
  注意:第二种方法只是读取文件
  InputStream insm=ReflectTest2.class.getClassLoader  ().getResourceAsStream("cn/itcast/config.properties");
  
  这是获取配置文件的第二种方法的另一种写法:ReflectTest2.class直接调用  getResourceAsStream("config.properties")方法
  getResourceAsStream("config.properties");里面直接写文件名,因为这是相对类  ReflectTest2的路径的,默认就是在类ReflectTest2的路径下找
  如果前面多了一个"/",getResourceAsStream("/config.properties")表示  classPath的跟目录开始找
  
  InputStream insm=ReflectTest2.class.getResourceAsStream  ("config.properties");
  */
  prop.load(ins);//把输入流关联的文件,加载到集合中
  String className=prop.getProperty("className");//用键得到值
  //得到类名后,创建对象
  Collection con=(Collection)Class.forName(className).newInstance();
  
  ReflectPoint pt1=new ReflectPoint(3,3);
  ReflectPoint pt2=new ReflectPoint(2,2);
  ReflectPoint pt3=new ReflectPoint(3,3);
  ReflectPoint pt4=new ReflectPoint(5,5);
  
  con.add(pt1);
  con.add(pt2);
  con.add(pt3);
  con.add(pt4);
  
  //打印集合的大小
  System.out.println(con.size());
 }
}

13 内省IntroSpector
IntroSpector-->JavaBeen-->特殊的java类(有setXxx()和getYyy()方法的类叫做JavaBeen)
那么如果一个类是JavaBeen,Xxx和Yyy就是它的属性
如果Xxx的第二个字母是小写的,则把第一个字母变成小写
如果第二个字母是大写的,则把第一个字母不变
/*
例子:Person类
*/
class Person
{
 private int age;
 public void setAge(int age)
 {
  this.age=age;
 }
 public int getAge()
 {
  return this.age;
 }
}
 

 

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值