有人说Java是一门静态语言。那么何为静态语言,动态语言又是什么?

1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运 行时代码可以根据某些条件改变自身结构。 主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如C、 C++。

Java不是动态语言,但也不能简单的说成静态语言。Java可以称之为“准动态语言”。即Java有一定的动 态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。
Java的动态性让编程的时候更加灵活!

因此我们可以通过反射,将Java“变成”动态语言,即可以通过反射改变程序运行时的结构。举一个简单的例子模拟一下:

package day_12_30.reflection_test;

import day_12_30.reflection.java.Person;

import java.util.Date;
import java.util.Random; /**
* @author soberw
* @Classname RefTest
* @Description 体会反射的动态性
* @Date 2021-12-30 20:56
*/
public class RefTest { public static void main(String[] args) throws Exception {
Random random = new Random();
for (int i = 0; i < 10; i++) {
int j = random.nextInt(3);
Class clazz = switch (j) {
case 1 -> User.class;
case 2 -> Date.class;
default -> Person.class;
};
Object o = clazz.getDeclaredConstructor().newInstance();
System.out.println(o);
}
}
} class User {
private String name;
private int age;
public User() {}
{
this.age = 18;
this.name = "wang";
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}


在程序跑起来之前谁也不知道程序会造哪个类的对象。

下面我再简单举例两个Java的反射机制在实际开发中的应用场景,帮助大家更好的掌握反射:
例如我们在连接数据库的时候,随着需求的改变,可能今天会用到MySQL,明天又用到Oracle了,那我们总不能频繁的去创建对象,多麻烦。这时候我们就可以用反射的机制去设计实现,简单举例一下:
我有一个连接接口:

public interface Connect {
/**
* 保存数据库文件
*/
void safe();
}

有两个实现类:

public class MysqlConnect implements Connect{
@Override
public void safe() {
System.out.println("数据保存在mysql中...");
}
} public class OracleConnect implements Connect{
@Override
public void safe() {
System.out.println("数据保存在oracle中...");
}
}

现在我想随时去切换调用哪个数据库,只需要声明一个文件,保存全类名,这里命名为:bean.properties


然后我再创建一个工厂类,通过工厂类去调用数据库连接:

package day_12_31.mybean;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties; /**
* @author soberw
* @Classname MyBeanFactory
* @Description
* @Date 2021-12-31 9:00
*/
public class MyBeanFactory {
private static Properties props;
private static String className;
static{
String path = MyBeanFactory.class.getClassLoader().getResource("data/bean.properties").getPath();
props = new Properties();
try {
props.load(new FileInputStream(path));
} catch (IOException e) {
e.printStackTrace();
}
className = props.getProperty("user");
} public static Object getBean(){
Class clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}

测试如下:

public class FactoryTest {
public static void main(String[] args) {
Object bean = MyBeanFactory.getBean();
Connect c = (Connect) bean;
c.safe();
}
}


此时如果想改为mysql连接,只需在配置文件里改就行了:

当然方法远不止这一种,我们都知道,注解在Java高级部分也是非常重要的,很多框架大量运用到了注解,比如JPA是基于注解的,Spring2.5以上都是基于注解的,甚至在一定程度上来说:框架 = 注解 + 反射 + 设计模式。
而且使用注解比配置文件会更高效,满足了工厂设计模式的高内聚低耦合的性质。
下面我就简单模拟一下:
首先声明一个注解类:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
}

编写新的工厂类:

package day_12_31.mybean;

import java.io.File;
import java.util.ArrayList;
import java.util.List; /**
* @author soberw
* @Classname AnnotationFactory
* @Description
* @Date 2021-12-31 10:00
*/
public class AnnotationFactory {
private static String packageName = "day_12_31.mybean";
private static List<String> list = new ArrayList<>(); static {
StringBuilder path = new StringBuilder(AnnotationFactory.class.getClassLoader().getResource("").getPath());
String[] split = packageName.split("[.]");
for (String s : split) {
path.append(s).append("/");
}
File file = new File(path.toString());
File[] files = file.listFiles();
for (File f : files) {
String s = f.getName().substring(0, f.getName().lastIndexOf("."));
String className = packageName + "." + s;
list.add(className);
}
} public static Object getBean() {
for (String s : list) {
try {
if (Class.forName(s).isAnnotationPresent(MyAnnotation.class)) {
return Class.forName(s).getDeclaredConstructor().newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}

测试一下:

package day_12_31.mytest;

import day_12_31.mybean.AnnotationFactory;
import day_12_31.mybean.Connect; /**
* @author soberw
* @Classname AnnnotationFactoryTest
* @Description
* @Date 2021-12-31 9:59
*/
public class AnnotationFactoryTest {
public static void main(String[] args) {
Object bean = AnnotationFactory.getBean();
if (bean != null) {
Connect c = (Connect) bean;
c.safe();
}else {
System.out.println("数据保存失败...");
}
}
}


我们想要连接哪个数据库,就在连接类上添加注解就行了,也不用再去修改配置文件了:

那么这就是Java中反射的应用场景,当然,在实际中,其应用场景会更加广泛,所以,熟练掌握反射,在实际开发中会更加得心应手!

简单模拟Java中反射的应用场景的更多相关文章

  1. 简单聊聊java中的final关键字

    简单聊聊java中的final关键字 日常代码中,final关键字也算常用的.其主要应用在三个方面: 1)修饰类(暂时见过,但是还没用过); 2)修饰方法(见过,没写过); 3)修饰数据. 那么,我们 ...

  2. Java中反射的三种常用方式

    Java中反射的三种常用方式 package com.xiaohao.test; public class Test{ public static void main(String[] args) t ...

  3. java中反射学习整理

    转载请注明:http://blog.csdn.net/j903829182/article/details/38405735 反射主要是指程序能够訪问.检測和改动它本身的状态或行为的一种能力. jav ...

  4. Java中反射的实现方式

    所谓反射,是指在运行时状态中,获取类中的属性和方法,以及调用其中的方法的一种机制.这种机制的作用在于获取运行时才知道的类(Class)及其中的属性(Field).方法(Method)以及调用其中的方法 ...

  5. Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别

    一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:   其中

  6. Java中反射机制详解

    序言 在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射, ...

  7. 并发王者课 - 青铜 2:峡谷笔记 - 简单认识Java中的线程

    在前面的<兵分三路:如何创建多线程>文章中,我们已经通过Thread和Runnable直观地了解如何在Java中创建一个线程,相信你已经有了一定的体感.在本篇文章中,我们将基于前面的示例代 ...

  8. js 模拟java 中 的map

    //js模拟map Map = { obj : {}, put : function(key , value){ this.obj[key] = value; }, get : function(ke ...

  9. Java中反射与常用方法

    java通常是先有类再有对象,有对象我就可以调用方法或者属性. 反射其实是通过Class对象来调用类里面的方法.通过反射可以调用私有方法和私有属性.大部分框架都是运用反射原理.   如何获得Class ...

随机推荐

  1. Linux密码文件介绍

    1. 查看shadow文件内容```cat /etc/shadow```可以看到shadow文件内容,例如:```root:$1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.:148 ...

  2. 《selenium2 python自动化测试》(高清).PDF,免费无需任何解压密码

    链接:https://pan.baidu.com/s/1eAI0mXvJeblBn2Tn9WClEA 提取码:7m5u

  3. vuex 中使用Element-ui的message

    首先引入Message 其次,在mutations中调用Message 注意:缓存的问题,如果没有弹出框架出现,多重启几次服务 参考资料: https://blog.csdn.net/weixin_4 ...

  4. python中类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法

    类对象.类属性与实例对象.实例属性的区别 在Python中一切皆是对象,类是一个特殊的对象即类对象,描述类的属性称为类属性.类属性在内存中只有一份,在__init__外部定义. 通过类创建的对象称为实 ...

  5. 华为云 Kubernetes 管理员实训 五 课后作业

    练习1 部署一个Deployment应用,使用secret普通卷,该应用启动依赖此secret. Deployment的名称为<hwcka-005-1-你的华为云id> 将所用命令.创建的 ...

  6. [Docker] 在CentOS6.8 安装 Docker

    运行docker Linux内核版本需要在3.8以上,针对centos6.5 内核为2.6的系统需要先升级内核.不然会特别卡,退出容器. # 查看当前版本: cat /etc/issue # 导入pu ...

  7. 简单的Dos 命令

    1.1.如何操作DOS命令 开始---运行---输入cmd--回车 或者 Win + R ---运行---输入cmd--回车 1.2.基本命令 1. 命令:color f0 帮助:color ? 作用 ...

  8. 灵雀云新一期DevOps认证培训圆满结束,下期学员招募同步开启

    近日,灵雀云最新一期EXIN DevOps认证培训在北京圆满结束,来自某知名运营商领域ISV的近40名学员以百分百的通过率为此次培训画上圆满的句号. 灵雀云是国内首家在DevOps培训领域与EXIN合 ...

  9. MySQL 中如何定位 DDL 被阻塞的问题

    经常碰到开发.测试童鞋会问,线下开发.测试环境,执行了一个DDL,发现很久都没有执行完,是不是被阻塞了?要怎么解决? 包括在群里,也经常会碰到类似问题:DDL 被阻塞了,如何找到阻塞它的 SQL ? ...

  10. Spring循环依赖原理

    Spring循环依赖的原理解析 1.什么是循环依赖? ​ 我们使用Spring的时候,在一个对象中注入另一个对象,但是另外的一个对象中也包含该对象.如图: 在Student中包含了teacher的一个 ...