静态VS动态语言
动态语言(弱类型语言)是运行时才确定数据类型的语言,变量在使用之前无需申明类型,通常变量的值是被赋值的那个值的类型。比如Php、Asp、JavaScript、Python、Perl等等。
var s ="hello";
var i = 0;
var b = true;
静态语言(强类型语言)是编译时变量的数据类型就可以确定的语言,大多数静态语言要求在使用变量之前必须生命数据类型。比如Java、C、C++、C#等。
String s="hello"; //String 类型的变量
boolean b=true; //boolean 类型的变量
int i=0; //int 类型的变量
弱类型语言是数据类型可以被忽略的语言。它与强类型语言相反,一个变量可以赋不同数据类型的值。一个变量的类型是由其上下文决定的,效率更高。
强类型语言是必须强制确定数据类型的语言,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这种数据类型。一个变量的类型是申明的时候就已经确定的,更安全。
静态语言由于强制声明数据类型,让开发工具(IDE)对代码有很强的判断能力,在实现复杂的业务逻辑和开发大型商业系统、以及那些声明周期很长的应用中,开发者可以依托强大的IDE来更高效、更安全地开发。
动态语言思维不受约束,可以任意发挥,把更多的精力放在产品本身上;集中思考业务逻辑实现,思考过程就是实现过程。
反射(Reflection)
什么是反射?
反射的概念:在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
一般而言,说到动态语言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVA和C++一样,都不是动态语言。但JAVA它却有着一个非常突出的动态相关机制:反射。通过反射,Java可以于运行时加载、探知和使用编译期间完全求和的类、生成其对象实体,调用其方法或者对属性设值。所以Java算是一个半动态的语言吧。
Class c = Class.forName("java.lang.String");
加载完类之后,在堆内存的方法区中就会产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了类的结构信息,我们可以通过这个对象看到类的信息。这个对象就像一面镜子,透过这个镜子看到类的信息,所以我们形象的称之为:反射:
动态性质
- 运行时生成对象实例;
- 运行期间调用方法;
- 运行时更改属性
反射机制能实现的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意怀个类所具有的方法和属性
- 在运行时调用任意一个对象的方法
- 生成动态代理
优缺点
- 优点:可以实现动态创建对象和编译,体现出很大的灵活性
- 缺点:对性能有影响。使用反射基本上是一种解释操作,我们告诉JVM,我们需要做什么并且它会满足我们的要求,这类操作总是慢于 直接执行相同的操作
应用
- 创建一个实体类User
public class User {
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
- 获取Class类的实例的几种方法
//若已知具体的类,通过类的class属性获取
Class c1 = User.class;
//已知某个类的实例,通过该实例的getClass()方法获取Class对象
Class c2 = user.getClass();
//已知一个类的全名,且该类在类路径下,通过Class.forName("")获取,可能抛出ClassNotFoundException
Class c3 = Class.forName("org.example.reflection.User");
- 获取类运行时结构
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c = Class.forName("org.example.reflection.User");
System.out.println(c.getName()); //包名+类名
System.out.println(c.getSimpleName());//类名
System.out.println("----------------------------");
//获取类的属性
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("----------------------------");
//获取本类中指定的属性
Field name = c.getDeclaredField("name");
System.out.println(name);
System.out.println("-----------------------------");
//获取类的方法
Method[] methods = c.getMethods();//获取本类以及父类的public方法
for (Method method : methods) {
System.out.println("method:"+method);
}
System.out.println("----------------------------------");
Method[] declaredMethods = c.getDeclaredMethods();//获取本类的所有的方法
for (Method declaredMethod : declaredMethods) {
System.out.println("declaredMethod:"+declaredMethod);
}
System.out.println("------------------------------");
//获取构造方法
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
- 动态的创建对象
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获取class实例
Class c = Class.forName("org.example.reflection.User");
//通过newInstance() 构造一个User对象
User user = (User) c.newInstance();//调用了无参构造器
System.out.println(user);
System.out.println("-------------------");
//通过构造器创建一个对象
Constructor constructor = c.getDeclaredConstructor(String.class,int.class,int.class);
User user1 = (User) constructor.newInstance("马云", 001, 55);
System.out.println(user1);
System.out.println("--------------------");
//通过反射构造一个对象
User user2 = (User) c.newInstance();
//通过反射获取一个方法
Method setName = c.getDeclaredMethod("setName",String.class);
//invoke激活的意思
setName.invoke(user2,"马云");
System.out.println(user2.getName());
System.out.println("------------------");
User user3 = (User) c.newInstance();
//通过反射获取一个属性
Field name = c.getDeclaredField("name");
//不能直接操作私有属性,关闭程序的安全检测setAccessible(true),默认是false
name.setAccessible(true);
name.set(user3,"雷军");
System.out.println(user3.getName());
}
- 获取注解的信息
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//获取class实例
Class c = Class.forName("org.example.reflection.Student");
//通过反射获取注解
Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//通过反射获取注解的value的值
TableAnnotation table = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
String[] value = table.value();
for (String s : value) {
System.out.println(s);
}
//获取类指定的注解
Field f = c.getDeclaredField("name");
FieldAnnotation annotation = f.getAnnotation(FieldAnnotation.class);
System.out.println(annotation.columnName());
System.out.println(annotation.length());
System.out.println(annotation.type());
}
}
@TableAnnotation("db_student")
class Student{
@FieldAnnotation(columnName = "db_name",type = "varchar",length = 10)
private String name;
@FieldAnnotation(columnName = "db_age",type = "int",length = 3)
private int age;
@FieldAnnotation(columnName = "db_id",type = "int",length = 10)
private int id;
public Student() {
}
public Student(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
//类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableAnnotation {
String[] value() default "";//默认为空
}
//属性注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface FieldAnnotation {
String columnName();//属性名
String type();//属性类型
int length();//字段长度
}