1.1 java语言有哪些优点?

1.java语言为纯面向对象的语言。

2.平台无关性。java语言的优点便是“一次编译,到处执行”。编译后的程序不会被平台所约束,因此java语言有很好的移植性。

3.java提供了许多内置的类库,将代码封装好来给操作人员使用,从而大大减少开发人员的时间。

4.提供了对web应用的开发的支持。

5.具有较好的安全性和健壮性。

6.去除了c++语言中难以理解,容易混淆的特性,例如头文件,指针,结构,单元运算符重载,虚拟基础类,多重继承等,所以java语言是由c++语言改进并重新设计而来的

1.2 java语言和c/c++有什么异同。

java和C++都是面向对象的语言,都使用了面向对象的思想(例如封装,继承,多态),由于面向对象有许多非常好的特性(继承,组合等),因此二者都有很好的重用性。

下面重点说一下不同点:

1.java为解释型语言,c/c++为编译型语言,java代码由java编译器编译成字节码,然后由JVM解释,C语言代码经过编译和链接生成可执行的二进制代码,因此java的执行速度比c++慢,但是java可跨平台执行,c/c++不能

2.java语言没有指针

3.java只能实现单重继承,但是可以引入多个接口

4.java为纯面向对象语言,所有代码必须在类里实现

5.java语言提供了垃圾回收器来实现对垃圾的自动回收,c++语言中需要开发人员去管理对内存的分配。C语言,通常会把释放资源的代码放在析构函数中,Java没有但是有finalize()方法。

java语言不支持运算符重载,C语言支持

java不支持默认函数参数,c语言支持

java不提供goto语句,c/c++支持,但是在java中goto为保留关键字

java不支持自动强制类型装换,c语言支持

java具有平台无关性,就是对每种数据类型分配固定长度。

java提供对注释文档的内建支持

java包含了一些标准库

1.3 为什么使用public static void main(String[] args)方法?

main是程序的入口方法,所以程序执行时第一个执行的方法就是main方法。

main()方法定义的其他几种格式:

1.static pubic void main(String[] args)

static 和public无先后顺序

2.public static final void main(String[] args)

可以定义为final

3.static public synchronized void main(String[] args)

可以定义为synchronized

不管哪种定义方式,必须保证main()方法类型为void并且有static和public关键字修饰。不可以用abstract关键字,因为main()为程序的入口方法。

1.4静态块

静态块会在类被加载时调用,可以在main()方法前执行

例如:

public class jingtaikuai {

public static void main(String[] args) {
System.out.println("hello word");
}
static{
System.out.println("静态块");
}

}

执行结果:

静态块 hello word

1.5 java程序初始化顺序是怎样的

java程序的初始化一般遵循三个原则(优先级依次递减):

1.静态对象优先于非静态对象

2.父类优先于子类

3.按照成员变量定义顺序进行初始化

常见面试题:

下面代码的运行结果是什么?

class B extends Object{
static {
System.out.println("load b1");
}
public B(){
System.out.println("create b");
}
static{
System.out.println("load b2");
}
}
class A extends B{
static {
System.out.println("load a");
}
public A(){
System.out.println("create a");
}
}
public class 初始化顺序 {
public static void main(String[] args) {
new A();
}

}

执行结果:

load b1 load b2 load a create b create a

1.6 java作用域

在Java语言中,变量的类型主要有3种:成员变量、静态变量和局部变量

首先说静态变量跟局部变量

静态变量不依赖于特定的实例,而是被所有实例共享,也就是说,只要一个类被加载,JVM就会给类的静态变量分配

存储空间。因此可以通过类名.变量名来访问静态变量

局部变量的作用域与可见性为它所在的花括号内

类的成员变量的作用范围同类的实例化对象的作用范围相同。当类被实例化的时候,成员变量就会在内存中分配空间,并初始化。

直到类的实例化对象的生命周期结束时,成员变量的生命周期才结束。

作用域与可见性 当前类 同一package 子类 其他package
public
private × × ×
protected ×
default × ×

重点说一下protected和default:

protected:表名成员变量或方法对该类自身,与它在同一个包中的其他类,在其他包中的该类的子类都可见

default:表明该成员变量或方法只有自己和与其位于同一包内的类可见。

若父类与子类处于同一包内,则子类对父类的default成员变量或方法都有访问权限;若父类与子类处于不同的package内,则没有访问权限


还有需要注意的是,这些修饰符只能修饰成员变量,不能修饰局部变量。

private和protected不能用来修饰类

1.7 一个java文件中能否定义多个类

一个java文件中可以定义多个类,但是最多只能有一个类被public修饰,并且这个类的类名必须和文件名相同。

1.8 java的构造函数

一、什么是构造函数

java构造函数,也叫构造方法,是java中一种特殊的函数。函数名与相同,无返回值。

作用:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法。

在现实生活中,很多事物一出现,就天生具有某些属性和行为。比如人一出生,就有年龄、身高、体重、就会哭;汽车一出产,就有颜色、有外观、可以运行等。这些,我们就可以将这些天然的属性和行为定义在构造函数中,当new实例化对象时,也就具有这些属性和方法了,没必要再去重新定义了,从而加快了编程效率。

构造函数是对象一建立就运行,给对象初始化,就包括属性,执行方法中的语句。

而一般函数是对象调用才执行,用".方法名“的方式,给对象添加功能。

一个对象建立,构造函数只运行一次。

而一般函数可以被该对象调用多次。

二、构造函数的特点

1、函数名与类名相同

2、不用定义返回值类型。(不同于void类型返回值,void是没有具体返回值类型;构造函数是连类型都没有)

3、不可以写return语句。(返回值类型都没有,也就不需要return语句了

注:一般函数不能调用构造函数,只有构造函数才能调用构造函数。

三、示例

1、无参构造函数中只定义了一个方法。new对象时,就调用与之对应的构造函数,执行这个方法。不必写“.方法名”。

package javastudy;

public class ConfunDemo {
   public static void main(String[] args) {
       Confun c1=new Confun();            //输出Hello World。new对象一建立,就会调用对应的构造函数Confun(),并执行其中的println语句。
  }
}
class Confun{        
   Confun(){        //定义构造函数,输出Hello World
       System.out.println("Hellow World");
  }
}

输出:Hellow World

2、有参构造函数,在new对象时,将实参值传给private变量,相当于完成setter功能。

package javastudy;

public class ConfunDemo3 {
   public static void main(String[] args){
       Person z=new Person("zhangsan",3);        //实例化对象时,new Person()里直接调用Person构造函数并转转实参,相当于setter功能
       z.show();
  }
}

class Person{
   private String name;
   private int age;
   public Person(String n,int m){                //有参数构造函数,实现给private成员变量传参数值的功能
       name=n;
       age=m;        
  }
   //getter                                     //实例化对象时,完成了sett功能后,需要getter,获取实参值。
   public String getName(){
       return name;
  }
   public int getAget(){
       return age;
  }
   public void show(){                           //获取private值后,并打印输出
       System.out.println(name+"\n"+age);
  }
}

输出: zhangsan 3

以上代码,我们也可以将show()方法中的输出语句直接放在构造函数中,new对象时,即可直接输出值,如下

package javastudy;

public class ConfunDemo3 {
   public static void main(String[] args){
       Person z=new Person("zhangsan",3);        //实例化对象时,new Person()里直接调用Person构造函数并转转实参,同时执行输出语句
  }
}

class Person{
   private String name;
   private int age;
   public Person(String n,int m){                //有参数构造函数,实现给private成员变量传参数值的功能,同时直接输出值
       name=n;
       age=m;
       System.out.println(name+"\n"+age);
  }
}

输出: zhangsan 3

class ConFun
{
   public static void main(String[] args){
       Person z=new Person(20,"zhangsan");
       System.out.println(z.getAge()+z.getName());
  }
}

class Person
{
   private int age;
   private String name;
   public Person(int x,String y){
       age=x;
       name=y;
  }
   public int getAge(){
       return age;
  }
   public String getName(){
       
       return name;
  }
}

3、一个对象建立后,构造函数只运行一次

如果想给对象的值再赋新的值,就要使用set和get方法,此时是当做一般函数使用

如下:

package javastudy;

public class ConfunDemo4 {
   public static void main(String[] args) {
           PersonDemo s=new PersonDemo("李三",33);        //new对象时,即调用对应的构造函数,并传值。同时,不能new同一个对象多次,否则会报错。
           s.setName("李五");                            //对象建立后,想变更值时,就要用set/get方法,重新设置新的值
           s.setName("阿尔法狗");                        //并可调用对象多次。
           s.print();
  }
}
class PersonDemo{
   private String name;
   private int age;
   PersonDemo(String n,int m){                //建立有参构造函数,用于给两个private变量name、age赋值,同时输出值
       name=n;
       age=m;
       System.out.println("姓名:"+name+"年龄:"+age);
  }
   public void setName(String x){            //set方法,用于再次给name赋值
       name=x;        
  }
   public String getName(){                //get方法,用于获取name的赋值
       return name;
  }
   public void print(){
       System.out.println(name);
  }
}

输出结果:

姓名:李三年龄:33 阿尔法狗

四、默认构造函数

当一个类中没有定义构造函数时,系统会给该类中加一个默认的空参数的构造函数,方便该类初始化。只是该空构造函数是隐藏不见的。

如下,Person(){}这个默认构造函数是隐藏不显示的。

class Person
{  
   //Person(){}
}

当在该类中自定义了构造函数,默认构造函数就没有了。

如果仍要构造函数,则需要自己在类中手动添加。

五、构造函数的重载

构造函数也是函数的一种,同样具备函数的重载(Overloding)特性。

class Person
{  
   private String name;
   private int age;    Person()
  {
       System.out.println("A:name="+name+":::age="+age);
  }    Person(String n)
  {
       name = n;
       System.out.println("B:name="+name+":::age="+age);
  }    Person(String n,int a)
  {  
       name=n;
       age=a;
       System.out.println("C:name="+name+":::age="+age);
  } } class PersonDemo2
{
   public static void main(String[] args)
  {
       Person p1=new Person();
       Person p2=new Person("lishi");
       Person p3=new Person("lishi",10);
  }
}

输出结果: A:name=null:::age=0 B:name=lishi:::age=0 C:name=lishi:::age=10

class Person
{  
   private String name;
   private int age;    Person()
  {
       System.out.println("A:name="+name+":::age="+age);
       cry();
  }    Person(String n)
  {
       name = n;
       System.out.println("B:name="+name+":::age="+age);
       cry();
  }    Person(String n,int a)
  {  
       name=n;
       age=a;
       System.out.println("C:name="+name+":::age="+age);
       cry();   }
   void cry()
  {
       System.out.println("Cry...............");
  } } class PersonDemo2
{
   public static void main(String[] args)
  {
       Person p1=new Person();
       Person p2=new Person("lishi");
       Person p3=new Person("lishi",10);
  }
}

输出结果: A:name=null:::age=0 Cry............... B:name=lishi:::age=0 Cry............... C:name=lishi:::age=10 Cry...............

转自:http://www.cnblogs.com/ibelieve618/p/6364541.html

1.9 java中的clone方法

java中所有的类都继承自Object类,这个类提供了一个clone的方法,这个方法的作用是返回一个Object对象的复制。

使用步骤:

1.继承Cloneable 接口

2.重写clone()方法

3.clone方法中调用super.clone()

4.把浅复制的引用指向原型对象新的克隆体


一、简单用法

只需要在需要clone的对象上实现(implements)Cloneable接口,然后再在类中加上clone方法,在方法中只需要调用super.clone(),根据自己的需要实现即可。

public class Student implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
} @Override
protected Student clone() throws CloneNotSupportedException {
return (Student)super.clone();
}

public static void main(String[] args) {
Student stu = new Student();
stu.setAge(1);
stu.setName("aa");
System.out.println(stu + " age: " + stu.getAge() + " name: " + stu.getName());
try {
Student sC = stu.clone();
System.out.println(sC + " sC.age: " + sC.getAge() + " sC.name: " + sC.getName());
sC.setAge(12);
sC.setName("bb");
System.out.println(stu + " age: " + stu.getAge() + " name: " + stu.getName());
System.out.println(sC + " sC.age: " + sC.getAge() + " sC.name: " + sC.getName());
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

输出结果:

testClone.Student@15db9742 age: 1 name: aa testClone.Student@6d06d69c sC.age: 1 sC.name: aa testClone.Student@15db9742 age: 1 name: aa testClone.Student@6d06d69c sC.age: 12 sC.name: bb

分析结果:1、根据输出结果中前边的类名,可以得出被克隆对象的与原来的对象是同一种类型。2、根据内存地址(hashcode)知道,被克隆对象的与原来的对象是存在于内存中的不同的两个对象。所以后边有一个赋值,对原来对象没有任何影响。

二、“影子”克隆与深度克隆

首先看一个例子:

class Bag{//学生的书包
private int width;
private String logo;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
}

public class Student2 implements Cloneable {
private String name;
private int age;
private Bag bag; public Bag getBag() {
return bag;
}
public void setBag(Bag bag) {
this.bag = bag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

@Override
protected Student2 clone() throws CloneNotSupportedException {
return (Student2)super.clone();
}

public static void main(String[] args) {
Student2 stu = new Student2();
stu.setAge(1);
stu.setName("aa");
Bag b = new Bag();
b.setWidth(10);
b.setLogo("Nike");
stu.setBag(b);
printStudent(stu);
try {
Student2 sC = stu.clone();
printStudent(sC);
sC.setAge(12);
sC.setName("bb");
sC.getBag().setWidth(100);//改变书包的属性
sC.getBag().setLogo("JNike");
printStudent(stu);
printStudent(sC);
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* 输出
* @param stu
*/
private static void printStudent(Student2 stu) {
System.out.println(stu + " age: " + stu.getAge() + " name: " + stu.getName() +
" bag: " + stu.getBag() + "(" + stu.getBag().getLogo() + " width: " +
stu.getBag().getWidth() + ")");
}

} 输出结果: testClone.Student2@15db9742 age: 1 name: aa bag: testClone.Bag@6d06d69c(Nike width: 10) testClone.Student2@7852e922 age: 1 name: aa bag: testClone.Bag@6d06d69c(Nike width: 10) testClone.Student2@15db9742 age: 1 name: aa bag: testClone.Bag@6d06d69c(JNike width: 100) testClone.Student2@7852e922 age: 12 name: bb bag: testClone.Bag@6d06d69c(JNike width: 100)

分析:发现是不是跟预期的不太一样,通过第二个同学改变书包,但是第一个同学的书包也被改变了。并且通过内存地址可知,他们是同一对象(书包)。原因:调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内 容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对 象中相应的变量指向的是同一个对象。 这就是所谓的“影子”克隆。

解决方案:深度克隆,既是对里边的引用也要克隆。以下是实现:

class Bag implements Cloneable{//学生的书包
private int width;//宽
private String logo;//品牌
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
} @Override
protected Bag clone() throws CloneNotSupportedException {
return (Bag)super.clone();
}

}

public class Student3 implements Cloneable {
private String name;
private int age;
private Bag bag; public Bag getBag() {
return bag;
}
public void setBag(Bag bag) {
this.bag = bag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

@Override
protected Student3 clone() throws CloneNotSupportedException {
Student3 stu = (Student3)super.clone();
stu.bag = bag.clone();
return stu;
}

public static void main(String[] args) {
Student3 stu = new Student3();
stu.setAge(1);
stu.setName("aa");
Bag b = new Bag();
b.setWidth(10);
b.setLogo("Nike");
stu.setBag(b);
printStudent(stu);
try {
Student3 sC = stu.clone();
printStudent(sC);
sC.setAge(12);
sC.setName("bb");
sC.getBag().setWidth(100);//改变书包的属性
sC.getBag().setLogo("JNike");
printStudent(stu);
printStudent(sC);
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* 输出
* @param stu
*/
private static void printStudent(Student3 stu) {
System.out.println(stu + " age: " + stu.getAge() + " name: " + stu.getName() +
" bag: " + stu.getBag() + "(" + stu.getBag().getLogo() + " width: " +
stu.getBag().getWidth() + ")");
}

}

输出: testClone.Student3@15db9742 age: 1 name: aa bag: testClone.Bag@6d06d69c(Nike width: 10) testClone.Student3@7852e922 age: 1 name: aa bag: testClone.Bag@4e25154f(Nike width: 10) testClone.Student3@15db9742 age: 1 name: aa bag: testClone.Bag@6d06d69c(Nike width: 10) testClone.Student3@7852e922 age: 12 name: bb bag: testClone.Bag@4e25154f(JNike width: 100)

1.10 什么是反射机制

Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功能称为Java 的反射机制。

Class 类与java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了Field,Method,Constructor类(每个类都实现了Member 接口)。这些类型的对象时由JVM 在运行时创建的,用以表示未知类里对应的成员。

这样你就可以使用Constructor 创建新的对象,用get() 和set() 方法读取和修改与Field 对象关联的字段,用invoke() 方法调用与Method 对象关联的方法。另外,还可以调用getFields() getMethods() 和 getConstructors() 等很便利的方法,以返回表示字段,方法,以及构造器的对象的数组。这样匿名对象的信息就能在运行时被完全确定下来,而在编译时不需要知道任何事情。

二、获取字节码的方式

在Java 中可以通过三种方法获取类的字节码(Class)对象

  • 通过Object 类中的getClass() 方法,想要用这种方法必须要明确具体的类并且创建该类的对象。

  • 所有数据类型都具备一个静态的属性.class 来获取对应的Class 对象。但是还是要明确到类,然后才能调用类中的静态成员。

  • 只要通过给定类的字符串名称就可以获取该类的字节码对象,这样做扩展性更强。通过Class.forName() 方法完成,必须要指定类的全限定名,由于前两种方法都是在知道该类的情况下获取该类的字节码对象,因此不会有异常,但是Class.forName() 方法如果写错类的路径会报 ClassNotFoundException 的异常。

    ackage com.jas.reflect;

    public class ReflectTest {
       public static void main(String[] args) {

           Fruit fruit = new Fruit();
           Class<?> class1 = fruit.getClass();     //方法一

           Class<?> class2 = Fruit.class;     //方法二

           Class class3 = null;    
           try {    //方法三,如果这里不指定类所在的包名会报 ClassNotFoundException 异常
               class3 = Class.forName("com.jas.reflect.Fruit");
          } catch (ClassNotFoundException e) {
               e.printStackTrace();
          }

           System.out.println(class1 + " " +class2 + "   " + class3);

      }
    }

    class Fruit{}

三、通过反射机制获取类信息

通过反射机制创建对象,在创建对象之前要获得对象的构造函数对象,通过构造函数对象创建对应类的实例。

下面这段代码分别在运行期间创建了一个无参与有参的对象实例。由于getConstructor() 方法与newInstance() 方法抛出了很多异常(你可以通过源代码查看它们),这里就简写了直接抛出一个Exception,下同。

package com.jas.reflect;

import java.lang.reflect.Constructor;

public class ReflectTest {
   public static void main(String[] args) throws Exception {

       Class clazz = null;
       clazz = Class.forName("com.jas.reflect.Fruit");
       Constructor<Fruit> constructor1 = clazz.getConstructor();
       Constructor<Fruit> constructor2 = clazz.getConstructor(String.class);

       Fruit fruit1 = constructor1.newInstance();
       Fruit fruit2 = constructor2.newInstance("Apple");

  }
}

class Fruit{
   public Fruit(){
       System.out.println("无参构造器Run...........");
  }
   public Fruit(String type){
       System.out.println("有参构造器Run..........." + type);
  }

}

输出: 无参构造器Run……….. 有参构造器Run………..Apple

通过反射机制获取Class 中的属性

package com.jas.reflect;

import java.lang.reflect.Field;

public class ReflectTest {
   public static void main(String[] args) throws Exception {

       Class<?> clazz = null;
       Field field = null;

       clazz = Class.forName("com.jas.reflect.Fruit");
       //field = clazz.getField("num");       getField() 方法不能获取私有的属性
       // field = clazz.getField("type");     访问私有字段时会报 NoSuchFieldException异常
       field = clazz.getDeclaredField("type");     //获取私有type 属性
       field.setAccessible(true);  //对私有字段的访问取消检查
       Fruit fruit = (Fruit) clazz.newInstance();  //创建无参对象实例
       field.set(fruit,"Apple");   //为无参对象实例属性赋值
       Object type = field.get(fruit); //通过fruit 对象获取属性值

       System.out.println(type);
  }
}

class Fruit{
   public int num;
   private String type;

   public Fruit(){
       System.out.println("无参构造器Run...........");
  }
   public Fruit(String type){
       System.out.println("有参构造器Run..........." + type);
  }

}

输出: 无参构造器Run……….. Apple

通过反射机制获取Class 中的方法并运行。

package com.jas.reflect;

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

public class ReflectTest {
   public static void main(String[] args) throws Exception {

       Class clazz = null;
       Method method = null;

       clazz = Class.forName("com.jas.reflect.Fruit");
       Constructor<Fruit> fruitConstructor = clazz.getConstructor(String.class);
       Fruit fruit = fruitConstructor.newInstance("Apple");    //创建有参对象实例

       method = clazz.getMethod("show",null);  //获取空参数show 方法
       method.invoke(fruit,null);  //执行无参方法

       method = clazz.getMethod("show",int.class); //获取有参show 方法
       method.invoke(fruit,20);  //执行有参方法

  }
}

class Fruit{
   private String type;

   public Fruit(String type){
       this.type = type;
  }
   public void show(){
       System.out.println("Fruit type = " + type);
  }
   public void show(int num){
       System.out.println("Fruit type = " + type + ".....Fruit num = " + num);
  }
}

输出: Fruit type = Apple Fruit type = Apple…..Fruit num = 20

四、反射机制简单应用(使用简单工厂创建对象)

Class.forName() 生成的结果是在编译时不可知的,因此所有的方法特征签名信息都是在执行时被提取出来的。反射机制能过创建一个在编译期完全未知的对象,并调用该对象的方法。

以下是反射机制与泛型的一个应用,通过一个工厂类创建不同类型的实例。

要创建对象的实例类Apple :

package com.jas.reflect;

public interface Fruit {}
class Apple implements Fruit{}

加载的配置文件config.properties:

Fruit=com.jas.reflect.Apple

工厂类BasicFactory :

package com.jas.reflect;

import java.io.FileReader;
import java.util.Properties;

public class BasicFactory {
   private BasicFactory(){}

   private static BasicFactory bf = new BasicFactory();
   private static Properties pro = null;

   static{
       pro = new Properties();
       try{    
           //通过类加载器加载配置文件
           pro.load(new FileReader(BasicFactory.class.getClassLoader().
                   getResource("config.properties").getPath()));
      }catch (Exception e) {
           e.printStackTrace();
      }
  }

   public static BasicFactory getFactory(){
       return bf;
  }

   //使用泛型获得通用的对象
   public  <T> T newInstance(Class<T> clazz){
       String cName = clazz.getSimpleName();   //获得字节码对象的类名
       String clmplName = pro.getProperty(cName);   //根据字节码对象的类名通过配置文件获得类的全限定名

       try{
           return (T)Class.forName(clmplName).newInstance();   //根据类的全限定名创建实例对象
      }catch (Exception e) {
           throw new RuntimeException(e);
      }

  }
}

创建对象实例:

package com.jas.reflect;

public class ReflectTest {
   public static void main(String[] args) throws Exception {
       Fruit fruit = BasicFactory.getFactory().newInstance(Fruit.class);
       System.out.println(fruit);
  }
}

输出 com.jas.reflect.Apple@4554617c

上面这个实例通过一个工厂创建不同对象的实例,通过这种方式可以降低代码的耦合度,代码得到了很大程度的扩展,以前要创建Apple 对象需要通过new 关键字创建Apple 对象,如果我们也要创建Orange 对象呢?是不是也要通过new 关键字创建实例并向上转型为Fruit ,这样做是麻烦的。

现在我们直接有一个工厂,你只要在配置文件中配置你要创建对象的信息,你就可以创建任何类型你想要的对象,是不是简单很多了呢?可见反射机制的价值是很惊人的。

Spring 中的 IOC 的底层实现原理就是反射机制,Spring 的容器会帮我们创建实例,该容器中使用的方法就是反射,通过解析xml文件,获取到id属性和class属性里面的内容,利用反射原理创建配置文件里类的实例对象,存入到Spring的bean容器中。

参考书籍: 《Java 编程思想》 Bruce Eckel 著 陈昊鹏 译

1.10 java创建对象的几种方式

  1. 通过new实例化一个对象

  2. 通过反射机制创建对象

  3. 通过clone方法创建一个对象

  4. 通过反序列化方式创建一个对象

1.11 package作用

package的作用

  • package的中文意思是“包”,它是一个比较抽象的逻辑概念,其宗旨是把.java文件 (Java源文件)、.class文件(编译后的文件)以及其他resource文件(例如.xml文件、.avi文件、.mp3文件、.txt文件等)有条理地进行一个组织,以供使用。它类似于Linux文件系统, 有一个根,从根开始有目录和文件,然后目录中嵌套目录。

  • 具体而言,package主要有以下两个作用: 第一,提供多层命名空间,解决命名冲突,通过使用package,使得处于不同package中的类可以存在相同的名字。 第二,对类按功能进行分类,使项目的组织更加清晰。当开发一个有非常多的类的项目时,如果不使用package对类进行分类,而是把所有类都放在一个package下,这样的代码不仅可读性差,而且可维护性也不好,会严重影响开发效率。

2)package的用法

  • package的用法一般如下(源文件所在目录为当前目录): 1.在每个源文件的开头加上"package packagename;",然后源文件所在目录下创建一个新目录,名称为 packapename。 2.用javac指令编译每个sourcename. java源文件,将生成的sourcename. classname文件复制到packagename 目录。 3.用 java 指令运行程序:java packagename. sourcename。

3)实例 以下是一个简单的程序示例。

package top.itcourse.pkg;

public class TestPackage {
   public static void main(String[] args) {
       System.out.println("Hello World!");
  }
}

结果: Hello World!

最新文章

  1. Windows phone应用开发[17]-xap提交异常处理
  2. C# GUID转换成16位字符串或19位数字并确保唯一
  3. 移动互联网实战--Web Restful API设计和基础架构
  4. Ajax案例:三级联动查询员工的信息(三张表进行内连接)
  5. js——倒计时
  6. 02-线性结构3 Pop Sequence
  7. 【剑指offer】近期公共祖先
  8. AutoLayout(转)
  9. php入门自学小展示
  10. [Regex Expression] Find Sets of Characters
  11. Spring Jdbc使用like模糊查询
  12. C#内获取泛型方法及扩展
  13. Pomelo的Router
  14. java.sql.SQLException: Value &#39;0000-00-00 00:00:00&#39; can not be represented as java.sql.Timestamp
  15. cmd 与 bash 基础命令入门
  16. webpack模块化管理和打包工具
  17. windbg分析运行在64位环境下的32位程序的dump
  18. ActiveX、OLE和COM的关系(转自百度文档)
  19. 逆FizzBuzz问题求最短序列
  20. STL基础4:deque

热门文章

  1. .net core 简单集成JWT报No authenticationScheme was specified, and there was no DefaultChallengeScheme found错误
  2. go语言从例子开始之Example38.排序
  3. 初学Java if选择语句
  4. nodeJs express4 框架
  5. MFC的Dlg和App什么区别?应用程序类与对话框类
  6. JavaWeb(二):Servlet
  7. Android 获取手机(ios,android)的设备唯一码(mac地址, IMEI)
  8. [CF1168D]Anagram Paths
  9. 【Linux】ssh执行远程命令awk 参数报错问题
  10. 【HDOJ6610】Game(序列带修莫队)