• 关于 认识继承 的搜索结果

问题

【精品问答】前端面试手册之JavaScript篇

前端问答 2019-12-01 22:04:08 130 浏览量 回答数 1

回答

一、OOP三大基本特性 OOP 面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏。 继承 继承是指这样一种能力,它可以使用现有的类的所有功能,并在无需重新编写原来类的情况下对这些功能进行扩展。 多态 多态指一个类实例的相同方法在不同情形有不同的表现形式。具体来说就是不同实现类对公共接口有不同的实现方式,但这些操作可以通过相同的方式(公共接口)予以调用。 二、OOD七大原则 面向对象设计(OOD)有七大原则,它们互相补充 开-闭原则 Open-Close Principle(OCP),即开-闭原则。开,指的是对扩展开放,即要支持方便地扩展;闭,指的是对修改关闭,即要严格限制对已有内容的修改。开-闭原则是最抽象也是最重要的OOD原则。简单工厂模式、工厂方法模式、抽象工厂模式中都提到了如何通过良好的设计遵循开-闭原则。 里氏替换原则 Liskov Substitution Principle(LSP),即里氏替换原则。该原则规定“子类必须能够替换其父类,否则不应当设计为其子类”。换句话说,父类出现的地方,都应该能由其子类代替。所以,子类只能去扩展基类,而不是隐藏或者覆盖基类。 依赖倒置原则 Dependence Inversion Principle(DIP),依赖倒置原则。它讲的是“设计和实现要依赖于抽象而非具体”。一方面抽象化更符合人的思维习惯;另一方面,根据里氏替换原则,可以很容易将原来的抽象替换为扩展后的具体,这样可以很好的支持开-闭原则。 接口隔离原则 Interface Segration Principle(ISP),接口隔离原则,“将大的接口打散成多个小的独立的接口”。由于Java类支持实现多个接口,可以很容易的让类具有多种接口的特征,同时每个类可以选择性地只实现目标接口。 单一职责原则 Single Responsibility Principle(SRP),单一职责原则。它讲的是,不要存在多于一个导致类变更的原因,是高内聚低耦合的一个体现。 迪米特法则/最少知道原则 Law of Demeter or Least Knowledge Principle(LoD or LKP),迪米特法则或最少知道原则。它讲的是“一个对象就尽可能少的去了解其它对象”,从而实现松耦合。如果一个类的职责过多,由于多个职责耦合在了一起,任何一个职责的变更都可能引起其它职责的问题,严重影响了代码的可维护性和可重用性。 合成/聚合复用原则 Composite/Aggregate Reuse Principle(CARP / CRP),合成/聚合复用原则。如果新对象的某些功能在别的已经创建好的对象里面已经实现,那么应当尽量使用别的对象提供的功能,使之成为新对象的一部分,而不要再重新创建。新对象可通过向这些对象的委派达到复用已有功能的效果。简而言之,要尽量使用合成/聚合,而非使用继承。

景凌凯 2020-03-19 23:49:30 0 浏览量 回答数 0

问题

多维度分析:抽象类和接口的区别

doudou1 2019-12-01 22:07:14 6456 浏览量 回答数 2

智能视觉生产免费体验

图像视频分割、图像编辑、图像分析,互娱、电商行业必备

回答

0段—非程序员: 初学编程者,遇到问题,完全是懵懵懂懂,不知道该怎么编程解决问题。也就是说,还是门外汉,还不能称之为“程序员”。计算机在他面前还是一个神秘的黑匣子。 1段—基础程序员: 学习过一段时间编程后,接到任务,可以编写程序完成任务。 编写出来的代码,正常情况下是能够工作的,但在实际运行中,碰到一些特殊条件就会出现各类BUG。也就是说,具备了开发Demo软件的能力,但开发的软件真正交付给客户使用,恐怕会被客户骂死。 程序员程序是写好了,但到底为什么它有时能正常工作,有时又不行,程序员自己也不知道。 运行中遇到了bug,或者需求改变,需要修改代码或者添加代码,很快程序就变得结构混乱,代码膨胀,bug丛生。很快,就连最初的开发者自己也不愿意接手维护这个程序了。 2段—数据结构: 经过一段时间的编程实践后,程序员会认识到“数据结构+算法=程序”这一古训的含义。他们会使用算法来解决问题。进而,他们会认识到,算法本质上是依附于数据结构的,好的数据结构一旦设计出来,那么好的算法也会应运而生。 设计错误的数据结构,不可能生长出好的算法。 记得某一位外国先贤曾经说过:“给我看你的数据结构!” 3段—面向对象: 再之后,程序员就会领略面向对象程序设计的强大威力。大多数现代编程语言都是支持面向对象的。但并不是说,你使用面向对象编程语言编程,你用上了类,甚至继承了类,你就是在写面向对象的代码了。 我曾经见过很多用Java,Python,Ruby写的面向过程的代码。 只有你掌握了接口,掌握了多态,掌握了类和类,对象和对象之间的关系,你才真正掌握了面向对象编程技术。 就算你用的是传统的不支持面向对象的编程语言,只要你心中有“对象”,你依然可以开发出面向对象的程序。 如,我用C语言编程的时候,会有意识的使用面向对象的技巧来编写和设计程序。用struct来模拟类,把同一类概念的函数放在一起模拟类。如果你怀疑用C语言是否能编写出面向对象的代码,你可以看一下Linux内核,它是用C语言编写的,但你也可以看到它的源代码字里行间散发出的浓浓的“对象”的味道。 答案来源于网络

养狐狸的猫 2019-12-02 02:20:35 0 浏览量 回答数 0

问题

【精品问答】python必备面试干货

问问小秘 2019-12-01 21:53:38 1125 浏览量 回答数 2

问题

【精品问答】前端技术1000个问答

茶什i 2019-12-01 22:05:13 206 浏览量 回答数 0

回答

初识 MyBatis MyBatis 是第一个支持自定义 SQL、存储过程和高级映射的类持久框架。MyBatis 消除了大部分 JDBC 的样板代码、手动设置参数以及检索结果。MyBatis 能够支持简单的 XML 和注解配置规则。使 Map 接口和 POJO 类映射到数据库字段和记录。 MyBatis 的特点 那么 MyBatis 具有什么特点呢?或许我们可以从如下几个方面来描述 MyBatis 中的 SQL 语句和主要业务代码分离,我们一般会把 MyBatis 中的 SQL 语句统一放在 XML 配置文件中,便于统一维护。 解除 SQL 与程序代码的耦合,通过提供 DAO 层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。SQL 和代码的分离,提高了可维护性。 MyBatis 比较简单和轻量 本身就很小且简单。没有任何第三方依赖,只要通过配置 jar 包,或者如果你使用 Maven 项目的话只需要配置 Maven 以来就可以。易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。 屏蔽样板代码 MyBatis 回屏蔽原始的 JDBC 样板代码,让你把更多的精力专注于 SQL 的书写和属性-字段映射上。 编写原生 SQL,支持多表关联 MyBatis 最主要的特点就是你可以手动编写 SQL 语句,能够支持多表关联查询。 提供映射标签,支持对象与数据库的 ORM 字段关系映射 ORM 是什么?对象关系映射(Object Relational Mapping,简称ORM) ,是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 提供 XML 标签,支持编写动态 SQL。 你可以使用 MyBatis XML 标签,起到 SQL 模版的效果,减少繁杂的 SQL 语句,便于维护。 MyBatis 整体架构 MyBatis 最上面是接口层,接口层就是开发人员在 Mapper 或者是 Dao 接口中的接口定义,是查询、新增、更新还是删除操作;中间层是数据处理层,主要是配置 Mapper -> XML 层级之间的参数映射,SQL 解析,SQL 执行,结果映射的过程。上述两种流程都由基础支持层来提供功能支撑,基础支持层包括连接管理,事务管理,配置加载,缓存处理等。 接口层 在不与Spring 集成的情况下,使用 MyBatis 执行数据库的操作主要如下: InputStream is = Resources.getResourceAsStream("myBatis-config.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); sqlSession = factory.openSession(); 其中的SqlSessionFactory,SqlSession是 MyBatis 接口的核心类,尤其是 SqlSession,这个接口是MyBatis 中最重要的接口,这个接口能够让你执行命令,获取映射,管理事务。 数据处理层 配置解析 在 Mybatis 初始化过程中,会加载 mybatis-config.xml 配置文件、映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息会形成相应的对象并保存到 Configration 对象中。之后,根据该对象创建SqlSessionFactory 对象。待 Mybatis 初始化完成后,可以通过 SqlSessionFactory 创建 SqlSession 对象并开始数据库操作。 SQL 解析与 scripting 模块 Mybatis 实现的动态 SQL 语句,几乎可以编写出所有满足需要的 SQL。 Mybatis 中 scripting 模块会根据用户传入的参数,解析映射文件中定义的动态 SQL 节点,形成数据库能执行的SQL 语句。 SQL 执行 SQL 语句的执行涉及多个组件,包括 MyBatis 的四大核心,它们是: Executor、StatementHandler、ParameterHandler、ResultSetHandler。SQL 的执行过程可以用下面这幅图来表示 MyBatis 层级结构各个组件的介绍(这里只是简单介绍,具体介绍在后面): SqlSession: ,它是 MyBatis 核心 API,主要用来执行命令,获取映射,管理事务。接收开发人员提供 Statement Id 和参数。并返回操作结果。Executor :执行器,是 MyBatis 调度的核心,负责 SQL 语句的生成以及查询缓存的维护。StatementHandler : 封装了JDBC Statement 操作,负责对 JDBC Statement 的操作,如设置参数、将Statement 结果集转换成 List 集合。ParameterHandler : 负责对用户传递的参数转换成 JDBC Statement 所需要的参数。ResultSetHandler : 负责将 JDBC 返回的 ResultSet 结果集对象转换成 List 类型的集合。TypeHandler : 用于 Java 类型和 JDBC 类型之间的转换。MappedStatement : 动态 SQL 的封装SqlSource : 表示从 XML 文件或注释读取的映射语句的内容,它创建将从用户接收的输入参数传递给数据库的 SQL。Configuration: MyBatis 所有的配置信息都维持在 Configuration 对象之中。 基础支持层 反射模块 Mybatis 中的反射模块,对 Java 反射进行了很好的封装,提供了简易的 API,方便上层调用,并且对反射操作进行了一系列的优化,比如,缓存了类的 元数据(MetaClass)和对象的元数据(MetaObject),提高了反射操作的性能。 类型转换模块 Mybatis 的别名机制,能够简化配置文件,该机制是类型转换模块的主要功能之一。类型转换模块的另一个功能是实现 JDBC 类型与 Java 类型的转换。在 SQL 语句绑定参数时,会将数据由 Java 类型转换成 JDBC 类型;在映射结果集时,会将数据由 JDBC 类型转换成 Java 类型。 日志模块 在 Java 中,有很多优秀的日志框架,如 Log4j、Log4j2、slf4j 等。Mybatis 除了提供了详细的日志输出信息,还能够集成多种日志框架,其日志模块的主要功能就是集成第三方日志框架。 资源加载模块 该模块主要封装了类加载器,确定了类加载器的使用顺序,并提供了加载类文件和其它资源文件的功能。 解析器模块 该模块有两个主要功能:一个是封装了 XPath,为 Mybatis 初始化时解析 mybatis-config.xml配置文件以及映射配置文件提供支持;另一个为处理动态 SQL 语句中的占位符提供支持。 数据源模块 Mybatis 自身提供了相应的数据源实现,也提供了与第三方数据源集成的接口。数据源是开发中的常用组件之一,很多开源的数据源都提供了丰富的功能,如连接池、检测连接状态等,选择性能优秀的数据源组件,对于提供ORM 框架以及整个应用的性能都是非常重要的。 事务管理模块 一般地,Mybatis 与 Spring 框架集成,由 Spring 框架管理事务。但 Mybatis 自身对数据库事务进行了抽象,提供了相应的事务接口和简单实现。 缓存模块 Mybatis 中有一级缓存和二级缓存,这两级缓存都依赖于缓存模块中的实现。但是需要注意,这两级缓存与Mybatis 以及整个应用是运行在同一个 JVM 中的,共享同一块内存,如果这两级缓存中的数据量较大,则可能影响系统中其它功能,所以需要缓存大量数据时,优先考虑使用 Redis、Memcache 等缓存产品。 Binding 模块 在调用 SqlSession 相应方法执行数据库操作时,需要制定映射文件中定义的 SQL 节点,如果 SQL 中出现了拼写错误,那就只能在运行时才能发现。为了能尽早发现这种错误,Mybatis 通过 Binding 模块将用户自定义的Mapper 接口与映射文件关联起来,系统可以通过调用自定义 Mapper 接口中的方法执行相应的 SQL 语句完成数据库操作,从而避免上述问题。注意,在开发中,我们只是创建了 Mapper 接口,而并没有编写实现类,这是因为 Mybatis 自动为 Mapper 接口创建了动态代理对象。 MyBatis 核心组件 在认识了 MyBatis 并了解其基础架构之后,下面我们来看一下 MyBatis 的核心组件,就是这些组件实现了从 SQL 语句到映射到 JDBC 再到数据库字段之间的转换,执行 SQL 语句并输出结果集。首先来认识 MyBatis 的第一个核心组件 SqlSessionFactory 对于任何框架而言,在使用该框架之前都要经历过一系列的初始化流程,MyBatis 也不例外。MyBatis 的初始化流程如下 String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSessionFactory.openSession(); 上述流程中比较重要的一个对象就是SqlSessionFactory,SqlSessionFactory 是 MyBatis 框架中的一个接口,它主要负责的是 MyBatis 框架初始化操作 为开发人员提供SqlSession 对象 SqlSessionFactory 有两个实现类,一个是 SqlSessionManager 类,一个是 DefaultSqlSessionFactory 类 DefaultSqlSessionFactory : SqlSessionFactory 的默认实现类,是真正生产会话的工厂类,这个类的实例的生命周期是全局的,它只会在首次调用时生成一个实例(单例模式),就一直存在直到服务器关闭。 SqlSessionManager : 已被废弃,原因大概是: SqlSessionManager 中需要维护一个自己的线程池,而使用MyBatis 更多的是要与 Spring 进行集成,并不会单独使用,所以维护自己的 ThreadLocal 并没有什么意义,所以 SqlSessionManager 已经不再使用。 ####SqlSessionFactory 的执行流程 下面来对 SqlSessionFactory 的执行流程来做一个分析 首先第一步是 SqlSessionFactory 的创建 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 1 从这行代码入手,首先创建了一个 SqlSessionFactoryBuilder 工厂,这是一个建造者模式的设计思想,由 builder 建造者来创建 SqlSessionFactory 工厂 然后调用 SqlSessionFactoryBuilder 中的 build 方法传递一个InputStream 输入流,Inputstream 输入流中就是你传过来的配置文件 mybatis-config.xml,SqlSessionFactoryBuilder 根据传入的 InputStream 输入流和environment、properties属性创建一个XMLConfigBuilder对象。SqlSessionFactoryBuilder 对象调用XMLConfigBuilder 的parse()方法,流程如下。 XMLConfigBuilder 会解析/configuration标签,configuration 是 MyBatis 中最重要的一个标签,下面流程会介绍 Configuration 标签。 MyBatis 默认使用 XPath 来解析标签,关于 XPath 的使用,参见 https://www.w3school.com.cn/xpath/index.asp 在 parseConfiguration 方法中,会对各个在 /configuration 中的标签进行解析 重要配置 说一下这些标签都是什么意思吧 properties,外部属性,这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。 <properties> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test" /> <property name="username" value="root" /> <property name="password" value="root" /> </properties> 一般用来给 environment 标签中的 dataSource 赋值 <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> 还可以通过外部属性进行配置,但是我们这篇文章以原理为主,不会介绍太多应用层面的操作。 settings ,MyBatis 中极其重要的配置,它们会改变 MyBatis 的运行时行为。 settings 中配置有很多,具体可以参考 https://mybatis.org/mybatis-3/zh/configuration.html#settings 详细了解。这里介绍几个平常使用过程中比较重要的配置 一般使用如下配置 <settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> </settings> typeAliases,类型别名,类型别名是为 Java 类型设置的一个名字。 它只和 XML 配置有关。 <typeAliases> <typeAlias alias="Blog" type="domain.blog.Blog"/> </typeAliases> 当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。 typeHandlers,类型处理器,无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。 在 org.apache.ibatis.type 包下有很多已经实现好的 TypeHandler,可以参考如下 你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很方便的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个 JDBC 类型。 objectFactory,对象工厂,MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。 public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return super.create(type); } public Object create(Class type, List constructorArgTypes, List constructorArgs) { return super.create(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public boolean isCollection(Class type) { return Collection.class.isAssignableFrom(type); } } 然后需要在 XML 中配置此对象工厂 <objectFactory type="org.mybatis.example.ExampleObjectFactory"> <property name="someProperty" value="100"/> </objectFactory> plugins,插件开发,插件开发是 MyBatis 设计人员给开发人员留给自行开发的接口,MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。MyBatis 允许使用插件来拦截的方法调用包括:Executor、ParameterHandler、ResultSetHandler、StatementHandler 接口,这几个接口也是 MyBatis 中非常重要的接口,我们下面会详细介绍这几个接口。 environments,MyBatis 环境配置,MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中 使用相同的 SQL 映射。 这里注意一点,虽然 environments 可以指定多个环境,但是 SqlSessionFactory 只能有一个,为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties); databaseIdProvider ,数据库厂商标示,MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 <databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> </databaseIdProvider> mappers,映射器,这是告诉 MyBatis 去哪里找到这些 SQL 语句,mappers 映射配置有四种方式 上面的一个个属性都对应着一个解析方法,都是使用 XPath 把标签进行解析,解析完成后返回一个 DefaultSqlSessionFactory 对象,它是 SqlSessionFactory 的默认实现类。这就是 SqlSessionFactoryBuilder 的初始化流程,通过流程我们可以看到,初始化流程就是对一个个 /configuration 标签下子标签的解析过程。 SqlSession 在 MyBatis 初始化流程结束,也就是 SqlSessionFactoryBuilder -> SqlSessionFactory 的获取流程后,我们就可以通过 SqlSessionFactory 对象得到 SqlSession 然后执行 SQL 语句了。具体来看一下这个过程‘ 在 SqlSessionFactory.openSession 过程中我们可以看到,会调用到 DefaultSqlSessionFactory 中的 openSessionFromDataSource 方法,这个方法主要创建了两个与我们分析执行流程重要的对象,一个是 Executor 执行器对象,一个是 SqlSession 对象。执行器我们下面会说,现在来说一下 SqlSession 对象 SqlSession 对象是 MyBatis 中最重要的一个对象,这个接口能够让你执行命令,获取映射,管理事务。SqlSession 中定义了一系列模版方法,让你能够执行简单的 CRUD 操作,也可以通过 getMapper 获取 Mapper 层,执行自定义 SQL 语句,因为 SqlSession 在执行 SQL 语句之前是需要先开启一个会话,涉及到事务操作,所以还会有 commit、 rollback、close 等方法。这也是模版设计模式的一种应用。 MapperProxy MapperProxy 是 Mapper 映射 SQL 语句的关键对象,我们写的 Dao 层或者 Mapper 层都是通过 MapperProxy 来和对应的 SQL 语句进行绑定的。下面我们就来解释一下绑定过程 这就是 MyBatis 的核心绑定流程,我们可以看到 SqlSession 首先调用 getMapper 方法,我们刚才说到 SqlSession 是大哥级别的人物,只定义标准(有一句话是怎么说的来着,一流的企业做标准,二流的企业做品牌,三流的企业做产品)。 SqlSession 不愿意做的事情交给 Configuration 这个手下去做,但是 Configuration 也是有小弟的,它不愿意做的事情直接甩给小弟去做,这个小弟是谁呢?它就是 MapperRegistry,马上就到核心部分了。MapperRegistry 相当于项目经理,项目经理只从大面上把握项目进度,不需要知道手下的小弟是如何工作的,把任务完成了就好。最终真正干活的还是 MapperProxyFactory。看到这段代码 Proxy.newProxyInstance ,你是不是有一种恍然大悟的感觉,如果你没有的话,建议查阅一下动态代理的文章,这里推荐一篇 (https://www.jianshu.com/p/95970b089360) 也就是说,MyBatis 中 Mapper 和 SQL 语句的绑定正是通过动态代理来完成的。 通过动态代理,我们就可以方便的在 Dao 层或者 Mapper 层定义接口,实现自定义的增删改查操作了。那么具体的执行过程是怎么样呢?上面只是绑定过程,别着急,下面就来探讨一下 SQL 语句的执行过程。 MapperProxyFactory 会生成代理对象,这个对象就是 MapperProxy,最终会调用到 mapperMethod.execute 方法,execute 方法比较长,其实逻辑比较简单,就是判断是 插入、更新、删除 还是 查询 语句,其中如果是查询的话,还会判断返回值的类型,我们可以点进去看一下都是怎么设计的。 很多代码其实可以忽略,只看我标出来的重点就好了,我们可以看到,不管你前面经过多少道关卡处理,最终都逃不过 SqlSession 这个老大制定的标准。 我们以 selectList 为例,来看一下下面的执行过程。 这是 DefaultSqlSession 中 selectList 的代码,我们可以看到出现了 executor,这是什么呢?我们下面来解释。 Executor 还记得我们之前的流程中提到了 Executor(执行器) 这个概念吗?我们来回顾一下它第一次出现的位置。 由 Configuration 对象创建了一个 Executor 对象,这个 Executor 是干嘛的呢?下面我们就来认识一下 Executor 的继承结构 每一个 SqlSession 都会拥有一个 Executor 对象,这个对象负责增删改查的具体操作,我们可以简单的将它理解为 JDBC 中 Statement 的封装版。 也可以理解为 SQL 的执行引擎,要干活总得有一个发起人吧,可以把 Executor 理解为发起人的角色。 首先先从 Executor 的继承体系来认识一下 如上图所示,位于继承体系最顶层的是 Executor 执行器,它有两个实现类,分别是BaseExecutor和 CachingExecutor。 BaseExecutor 是一个抽象类,这种通过抽象的实现接口的方式是适配器设计模式之接口适配 的体现,是Executor 的默认实现,实现了大部分 Executor 接口定义的功能,降低了接口实现的难度。BaseExecutor 的子类有三个,分别是 SimpleExecutor、ReuseExecutor 和 BatchExecutor。 SimpleExecutor : 简单执行器,是 MyBatis 中默认使用的执行器,每执行一次 update 或 select,就开启一个Statement 对象,用完就直接关闭 Statement 对象(可以是 Statement 或者是 PreparedStatment 对象) ReuseExecutor : 可重用执行器,这里的重用指的是重复使用 Statement,它会在内部使用一个 Map 把创建的Statement 都缓存起来,每次执行 SQL 命令的时候,都会去判断是否存在基于该 SQL 的 Statement 对象,如果存在 Statement 对象并且对应的 connection 还没有关闭的情况下就继续使用之前的 Statement 对象,并将其缓存起来。因为每一个 SqlSession 都有一个新的 Executor 对象,所以我们缓存在 ReuseExecutor 上的 Statement作用域是同一个 SqlSession。 BatchExecutor : 批处理执行器,用于将多个 SQL 一次性输出到数据库 CachingExecutor: 缓存执行器,先从缓存中查询结果,如果存在就返回之前的结果;如果不存在,再委托给Executor delegate 去数据库中取,delegate 可以是上面任何一个执行器。 Executor 的创建和选择 我们上面提到 Executor 是由 Configuration 创建的,Configuration 会根据执行器的类型创建,如下 这一步就是执行器的创建过程,根据传入的 ExecutorType 类型来判断是哪种执行器,如果不指定 ExecutorType ,默认创建的是简单执行器。它的赋值可以通过两个地方进行赋值: 可以通过 标签来设置当前工程中所有的 SqlSession 对象使用默认的 Executor <settings> <!--取值范围 SIMPLE, REUSE, BATCH --> <setting name="defaultExecutorType" value="SIMPLE"/> </settings> 另外一种直接通过Java对方法赋值的方式 session = factory.openSession(ExecutorType.BATCH); Executor 的具体执行过程 Executor 中的大部分方法的调用链其实是差不多的,下面是深入源码分析执行过程,如果你没有时间或者暂时不想深入研究的话,给你下面的执行流程图作为参考。 我们紧跟着上面的 selectList 继续分析,它会调用到 executor.query 方法。 当有一个查询请求访问的时候,首先会经过 Executor 的实现类 CachingExecutor ,先从缓存中查询 SQL 是否是第一次执行,如果是第一次执行的话,那么就直接执行 SQL 语句,并创建缓存,如果第二次访问相同的 SQL 语句的话,那么就会直接从缓存中提取。 上面这段代码是从 selectList -> 从缓存中 query 的具体过程。可能你看到这里有些觉得类都是什么东西,我想鼓励你一下,把握重点,不用每段代码都看,从找到 SQL 的调用链路,其他代码想看的时候在看,看源码就是很容易发蒙,容易烦躁,但是切记一点,把握重点。 上面代码会判断缓存中是否有这条 SQL 语句的执行结果,如果没有的话,就再重新创建 Executor 执行器执行 SQL 语句,注意, list = doQuery 是真正执行 SQL 语句的过程,这个过程中会创建我们上面提到的三种执行器,这里我们使用的是简单执行器。 到这里,执行器所做的工作就完事了,Executor 会把后续的工作交给 StatementHandler 继续执行。下面我们来认识一下 StatementHandler 上面代码会判断缓存中是否有这条 SQL 语句的执行结果,如果没有的话,就再重新创建 Executor 执行器执行 SQL 语句,注意, list = doQuery 是真正执行 SQL 语句的过程,这个过程中会创建我们上面提到的三种执行器,这里我们使用的是简单执行器。 到这里,执行器所做的工作就完事了,Executor 会把后续的工作交给 StatementHandler 继续执行。下面我们来认识一下 StatementHandler StatementHandler 的继承结构 有没有感觉和 Executor 的继承体系很相似呢?最顶级接口是四大组件对象,分别有两个实现类 BaseStatementHandler 和 RoutingStatementHandler,BaseStatementHandler 有三个实现类, 他们分别是 SimpleStatementHandler、PreparedStatementHandler 和 CallableStatementHandler。 RoutingStatementHandler : RoutingStatementHandler 并没有对 Statement 对象进行使用,只是根据StatementType 来创建一个代理,代理的就是对应Handler的三种实现类。在MyBatis工作时,使用的StatementHandler 接口对象实际上就是 RoutingStatementHandler 对象。 BaseStatementHandler : 是 StatementHandler 接口的另一个实现类,它本身是一个抽象类,用于简化StatementHandler 接口实现的难度,属于适配器设计模式体现,它主要有三个实现类 SimpleStatementHandler: 管理 Statement 对象并向数据库中推送不需要预编译的SQL语句。PreparedStatementHandler: 管理 Statement 对象并向数据中推送需要预编译的SQL语句。CallableStatementHandler:管理 Statement 对象并调用数据库中的存储过程。 StatementHandler 的创建和源码分析 我们继续来分析上面 query 的调用链路,StatementHandler 的创建过程如下 MyBatis 会根据 SQL 语句的类型进行对应 StatementHandler 的创建。我们以预处理 StatementHandler 为例来讲解一下 执行器不仅掌管着 StatementHandler 的创建,还掌管着创建 Statement 对象,设置参数等,在创建完 PreparedStatement 之后,我们需要对参数进行处理了。 如 如果用一副图来表示一下这个执行流程的话我想是这样 这里我们先暂停一下,来认识一下第三个核心组件 ParameterHandler ParameterHandler - ParameterHandler 介绍 ParameterHandler 相比于其他的组件就简单很多了,ParameterHandler 译为参数处理器,负责为 PreparedStatement 的 sql 语句参数动态赋值,这个接口很简单只有两个方法 ParameterHandler 只有一个实现类 DefaultParameterHandler , 它实现了这两个方法。 getParameterObject: 用于读取参数setParameters: 用于对 PreparedStatement 的参数赋值ParameterHandler 的解析过程 上面我们讨论过了 ParameterHandler 的创建过程,下面我们继续上面 parameterSize 流程 这就是具体参数的解析过程了,下面我们来描述一下 下面用一个流程图表示一下 ParameterHandler 的解析过程,以简单执行器为例 我们在完成 ParameterHandler 对 SQL 参数的预处理后,回到 SimpleExecutor 中的 doQuery 方法 上面又引出来了一个重要的组件那就是 ResultSetHandler,下面我们来认识一下这个组件 ResultSetHandler - ResultSetHandler 简介 ResultSetHandler 也是一个非常简单的接口 ResultSetHandler 是一个接口,它只有一个默认的实现类,像是 ParameterHandler 一样,它的默认实现类是DefaultResultSetHandler ResultSetHandler 解析过程 MyBatis 只有一个默认的实现类就是 DefaultResultSetHandler,DefaultResultSetHandler 主要负责处理两件事 处理 Statement 执行后产生的结果集,生成结果列表 处理存储过程执行后的输出参数 按照 Mapper 文件中配置的 ResultType 或 ResultMap 来封装成对应的对象,最后将封装的对象返回即可。 其中涉及的主要对象有: ResultSetWrapper : 结果集的包装器,主要针对结果集进行的一层包装,它的主要属性有 ResultSet : Java JDBC ResultSet 接口表示数据库查询的结果。 有关查询的文本显示了如何将查询结果作为java.sql.ResultSet 返回。 然后迭代此ResultSet以检查结果。 TypeHandlerRegistry: 类型注册器,TypeHandlerRegistry 在初始化的时候会把所有的 Java类型和类型转换器进行注册。 ColumnNames: 字段的名称,也就是查询操作需要返回的字段名称 ClassNames: 字段的类型名称,也就是 ColumnNames 每个字段名称的类型 JdbcTypes: JDBC 的类型,也就是 java.sql.Types 类型 ResultMap: 负责处理更复杂的映射关系 在 DefaultResultSetHandler 中处理完结果映射,并把上述结构返回给调用的客户端,从而执行完成一条完整的SQL语句。 内容转载自:CSDN博主:cxuann 原文链接:https://blog.csdn.net/qq_36894974/article/details/104132876?depth_1-utm_source=distribute.pc_feed.none-task&request_id=&utm_source=distribute.pc_feed.none-task

问问小秘 2020-03-05 15:44:27 0 浏览量 回答数 0

回答

Java是由James Gosling、Patrick Naughton、Chris Warth、Ed Frank 和 Mike Sheridan 于1991年在Sun公司构想出来的。开发第一个版本花费了18个月。这种语言最初称为Oak,在1995年被命名为Java。从1992年秋Oak最初实现到1995年春Java语言的公开发布,许多人对Java的设计和改进作出了贡献。Bill Joy、Arthur van Hoff、Jonathan Payne、Frank Yellin 和Tim Lindholm 是主要贡献者,他们的贡献使Java从最初原型逐渐成熟。 有些让人惊奇的是,Java最初的推动力不是Internet!相反,主要动机是对平台独立(即体系结构中立)语言的需要,这种语言可用于开发能够嵌入到各种消费电子设备(例如微波炉、遥控器等)的软件。您可能已经猜到了,许多不同类型的CPU被用作控制器,使用C或C++语言(以及大部分其他语言)的麻烦是,它们被设计为针对特定目标进行编译。尽管能够为各种类型的CPU编译C++程序,但是这需要一个完整的以该CPU为目标的C++编译器。问题是创建编译器很耗费时间,所以需要一种更容易并且更经济的解决方案。在寻找这样一种方案的尝试过程中,Gosling和其他人一起开始开发一种可移植的、平台独立的语言,可以使用这种语言生成在不同环境下运行各种CPU之上的代码。他们的努力最终导致了Java的出现。 在Java的细节被开发出来的同时,第二个并且也更加重要的因素出现了,它在Java的未来中扮演了关键的角色。第二个动力当然是万维网。假如Web的形成和Java的出现不在同一时间,那么Java虽然仍会有用,但可能只是一种用于为消费电子产品编写代码的没有名气的语言。然而,随着万维网的出现,Java被推到计算机语言设计的最前沿,因为Web也需要可移植的程序。 在为嵌入式控制器编写代码时经常遇到的可移植性问题,在尝试为Internet编写代码的过程中也出现了。到了1993年,这个问题对于Java设计小组的成员而言已经变得很明显了。实际上,最初针对解决小范围问题而设计的Java,也可以应用于更大范围的Internet。这一认识导致Java的关注点由消费类电子产品转移到了Internet编程。因此,虽然对体系结构中立的编程语言的需求提供了最初的思想火花,但最终是Internet成就了Java的成功。 Java从C 和 C++ 中继承了许多特性,这是有意而为之。Java设计人员清楚,使用与C语言类似的语法以及模仿C++的面向对象特性,可以使Java语言对于众多经验丰富的C/C++程序员更具有吸引力。除了表面类似外,Java还借鉴了帮助C和C++成功的其他一些特性。首先,Java的设计、测试和不断改进是由真正从事编程工作的人员完成的。它是扎根于设计人员的需要和经验的一种语言。因此Java是程序员的语言。其次,Java结构紧凑并且逻辑上协调一致。最后,除了Internet强加的哪些约束外,Java为程序员提供了完全的控制权。如果程序编写的好,程序本身就能反映出来。如果程序编写的不好,程序本身也能反映出来。因为存在这样的区别,所以Java不是一种用于培训的语言,而是针对专业程序员的语言。 因为Java与C++之间的相似性,可能会简单地将Java看作“Internet版的C++”。但是,如果这么认为将会是很大的错误。Java无论是从实践上还是在理论上都与C++有着很大的区别,虽然Java深受C++的影响,但它不是C++的增强版。例如,Java与C++既不向上兼容,也不向下兼容。当然与C++之间的相似性还是很明显的。并且如果您是一位C++程序员的话,会感觉Java很熟悉。另外一点:设计Java的目的不是取代C++。Java是针对解决特定的一系列问题而设计的。Java和C++将会长期共存。 计算机语言的发展取决于两个因素:适应环境的变化以及实现编程艺术的提高。促使Java发展的环境变化是对平台独立的需求,Internet上的分布式系统天生就需要平台独立的程序。同时,Java也体现了编程方式的变化。例如,Java增强并改进了C++使用的面向对象编程,增加了对多线程的支持,提供了简化Internet访问的库。总之,并不是Java的某个单一特征,而是整体上作为一种语言,使它如此非凡。Java是对新出现的高度分布计算领域需求的完美响应。Java对于Internet编程的意义,就如同C语言对系统编程一样:他们都是改变世界的革命性力量。

阳阳羊 2019-12-02 01:03:42 0 浏览量 回答数 0

问题

【精品问答】Python面试题汇总130问(框架篇)

珍宝珠 2019-12-01 22:04:22 1524 浏览量 回答数 0

回答

作为一个软件工程专业的过来人,希望我的回答能够帮助你,假设你每天坚持学习 首先找一本简单的教材,先对java有个基本的认识(大概看那么半个月就差不多了,随便下载一本入门的书就行了) 然后推荐你看<<java核心技术>>,分为上下两卷,已经是第八版了,大概有一千六七百页;当 你看完后,基本的java知识已经掌握了(记住,一定要多练习啊)(我那时候一个暑假看完第一遍,每天看将近十个小时加练习,但是要弄懂,呵呵,至少看个三四遍吧,这两本书只要能搞懂70%就很不错了) 这个时候你可以看看<<thinking in java>>中文名"java编程思想",这本书写的比较难,如果你看不懂,那么你要多做练习,慢慢看,如果看完了,而且懂了,那么证明你的java水平到达了一个更高的层次;(去参加面试的时候问的那些java知识完全可以应付过来了)(或者你可以先看下面的书,边看thinking in java这本书,这样也是可以的,而且学习的效率应该会高些) 然后java就会分方向,j2me(手机编程)不建议你去学这个(要学就学android手机编程),已经过时了;j2ee方向(Web编程),先学html,javaScript,css(这些书多得数不清,呵呵),然后就学servlet和jsp,《jsp应用开发详解》(入门) 《Servlet与JSP核心编程》(核心)这两本书还不错,然后就可以学SSH(三大框架,这个书一大堆), 学习struts的时候建议你从struts1开始学起《精通Struts基于MVC的Java Web设计与开发》,然后就可以学习struts2《Struts2权威指南》,接下来学习Hibernate《精通Hibernate:Java对象持久化技术详解》,最后学习Spring《spring2.0技术手册》(提示:只要你java基础学得好,这些东西都会学得很快) 这个时候你就要把注意力放在设计模式,数据结构和计算机算法上面来了, 设计模式可以先看<<深入浅出设计模式>> 然后再看<<java与模式>>, 数据结构建议你看清华大学严慰敏老师写的那本教材; 计算机算法要了解基本的排序,如果你不做底层,只做应用的话,没有必要去看那个<<算法导论>这本书太难了。 (设计模式,数据结构和算法才是真正的精髓,要有很多年的编程经验才能够使用得游刃有余,光看懂还不行的,一定要多练习,到了这个境界才是真正的java高手)(我学java有三年了,这是我的体会) 等你掌握前面的这些知识之后,推荐你看<<effective java>>,这本书是目前java领域公认的高级书籍。在项目中你肯定会遇到一些前端的知识,那么你得精通javascript,<<JavaScript权威指南>>(入门), <<JavaScript高级程序设计>>(进阶),这两本书弄懂了,那么学习jquery和extjs都会很快的。 还有要提醒你一下,对于初学者,不要使用eclipse编程工具,建议你先用记事本写程序,当你比较熟练了之后就可以使用eclipse这些工具了。 不要心急,不要图快,所有的书要一本本的慢慢看,多看几遍(一本书看上个四五遍,你就可以成高手,呵呵)。 java基础(j2se)的重点有:继承、多态、流、线程、网络编程、反射、集合、数据库连接、泛型、JNI技术、分布式技术还有解析xml也是很重要的,如果你想学android手机编程,那么SWING和AWT要熟悉一下。如果你不想学Web编程(j2ee),那么我建议你可以学android手机编程《Google+Android开发入门与实战》(入门) 《Google Android SDK开发范例大全》(深入)(建议把android当作业余爱好,把web编程当作主攻方向,因为j2ee包含了大量框架知识),书很多,可以自己去搜。多想 多看 多练才是王道,不要相信什么培训机构,这些都没啥用,真正学好只能靠你自己。 面向对象思想+java基础(j2se)+数据结构+设计模式+计算机算法 为核心,学好了这几个8000元/月轻而易举,什么都可以不学好,唯独这几科一定要学好,切记切记。 当然,随着你的技术水平的提高,你还会要学习其他的语言,不过这都是后话,等你把上面的东西掌握了,我再告诉你怎么学(高并发等内容),哈哈。 你现在还是在校的学生,那么请记住,不要沉迷于游戏,把时间用于学习上面的知识,千万别听一些人说什么'学校学的东西工作都用不到',完全是胡扯,我很负责任的告诉你,只有学校里学的东西才是真正有技术含量的东西,真正工作了,你就没有那么多时间来学习了(唉,感触很深呐) 以上的内容是我学习的总结,当然我走过很多弯路,现在我把这条正确的路径介绍给你,也是希望你能够少走弯路,希望几年之后,你能够比现在的我更牛X(呵呵,吹个小牛)。加油。参考资料来源:http://zhidao.baidu.com/question/404215211.html

晚来风急 2019-12-02 01:20:25 0 浏览量 回答数 0

回答

现在看来,anycmd构建时找到的最重要的指向标是:始终以(主体,客体)的两两组合为中心,始终将主客体组合看作干流,始终将那单个的9种AC元素看作是支流。###### 有可能,subject 这部分过细了? principal(Account、Organization、Role、Group)这几种很好。 ######是的。principal(Account、Organization、Role、Group)这几种算作用户主体,剩余几种算作系统主体。用户主体主要是面向人的,系统主体主要是面向系统的(我们的系统和和我们的系统连接的系统),通常普通用户不关心系统主体。###### 追加: 我们知道,在功能级访问控制中至少会有Account、Catalog、Role、Group、Function、Menu、AppSystem、Privilege这几种元素。并且之前我们认识到这若干种元素是可以任意两两组合的,(Account, Account)、(Account, Catalog)、(Catalog, Role)等每一种二元组都是可以有明确的访问控制意义的。到达数据级权限的时候就是又多出了一个元素:Object。这种Object元素也要与前面几种元素任意两两组合并且有明确的意义。每一种组合一定都是有意义的,合适的意义到底是什么这需要我们去发现。 最近发现前面那样的无方向的二元组的粒度不够。二元组合需要分裂为二元排列。比如(account1, account2)需要分裂为<account1, account2>和<account2, account1>,(catalog1, role1)需要分裂为<catalog1, role1>和<role1, catalog1>,(role1, function1)需要分裂为<role1, function1>和<function1, role1>等。 <Catalog,Role>和<Role,Catalog>是不同的,<Role,Catalog>也有意义。以前没发掘出<Role,Catalog>的意义,现在发现了。<Role,Catalog>的意义是限定role的作用范围,<role1,catalog1>和<role1,catalog2>共同限定了role1的作用范围只能是在catalog1和catalog2目录下,主体进入这俩目录的时候才会激活主体的role1角色,主体出了这俩目录时role1就被收回。而<catalog1, role1>的意思是授予catalog1主体目录下的主体role1角色。catalog1是主体目录,可以是组织机构(组织机构目录树上的每一个节点下组织的资源包括桌子、电脑、办公室等,重要的是包括“员工”这种主体类型的资源)。组织机构是一棵树,单继承的。如果subject1是catalog1.catalog1.001节点下的主体的话,由于<catalog1, role1>这条记录的存在,subject1就可以沿着组织机构树获得role1角色。 如果按照把一条二元组合记录分裂为两条二元排列记录这种模式思考的话会发现(Role, Function)可以被拆分为<Role, Function>和<Function, Role>。<Role, Function>是角色授权的意思,而<Function, Role>可以解释为:限制给定的功能可被授予的角色的范围。<function1, role1>、<function1, role2>、<function1, role3> 这三条记录共同限制function1只能被授予role1、role2、role3角色不能被授予role4角色。 由“Account、Catalog、Role、Group、Function、Menu、AppSystem、Privilege”这些元素组成的任意二元排列在权限引擎中都应有明确的意义,后续我们一一发现。至此终于完善了模型,一条二元排列记录由两个元素按照顺序组合得到,不可能再继续分裂了,再继续分裂就是对元素进行分裂了(对元素进行分裂是这样的分裂:比如Function这种类型的元素会被分裂为名称、入参、返回值,入参是个列表继续分裂,返回值也是列表也可以继续分裂。无论在什么层次运用组合和分裂,模式一定都是完全一样的,因为世界是分形的)。 看样子虽然以前的文字中一直使用的“组合”这个词, 代码 上却一直用的是“排列”,现在终于一致了。

kun坤 2020-06-07 13:54:43 0 浏览量 回答数 0

回答

计算机科学与技术专业课程 课程简介 1.数字逻辑电路: “数字逻辑”是计算机专业本科生的一门主要课程,具有自身的理论体系和很强的实践性。它是计算机组成原理的主要先导课程之一,是计算机应用专业关于计算机系统结构方面的主干课程之一。 课程的主要目的是使学生了解和掌握从对数字系统提出要求开始,一直到用集成电路实现所需逻辑功能为止的整个过程的完整知识。内容有数制和编码、布尔代数和逻辑函数、组合逻辑电路的分析和设计,时序逻辑电路的分析和设计,中、大规模集成电路的应用。通过对该课程的学习,可以为计算机组成原理、微型计算机技术、计算机系统结构等课程打下坚实的基础。 2.计算机组成原理: 本课程是计算机系本科生的一门重要专业基础课。在各门硬件课程中占有举足轻重的地位。它的先修课程是《数字逻辑电路》,后继课程有《微机接口技术》、《计算机系统结构》。从课程地位来说,本课程在先修课和后继课中起着承上启下的作用。主要讲解计算机五大部件的组成及工作原理,逻辑设计与实现方法,整机的互连技术,培养学生具有初步的硬件系统分析、设计、开发和使用的能力。具体内容包括:数制与码制、基本逻辑部件、运算方法与运算器、指令系统与寻址方式,中央处理器(CPU)的工作原理及设计方法。存储系统和输入/输出(I/O)系统等。通过该课程的学习,可以使学生较深地掌握单台计算机的组成及工作原理,进一步加深对先修课程的综合理解及灵活应用,为后继课程的学习建立坚实的基础知识。 3.微机接口技术: 本课程是计算机科学与技术专业学生必修的核心课程之一,它的先修课程为数字逻辑、计算机组成原理。本课程对于训练学生掌握硬件接口设计技术,熟悉微处理器和各种接口芯片的硬件设计和软件调试技术都有重要作用,在软件方面要求掌握汇编语言,在硬件方面要掌握中断、DMA、计数器/定时器等设计技术。通过该课程的学习使学生学会微机接口设计的基本方法和技能。 4.计算机系统结构: 计算机系统结构主要是研究高性能计算机组织与结构的课程。主要包括:计算机系统结构的基本概念、指令的流水处理与向量计算机、高性能微处理器技术、并行处理机结构及算法和多处理机技术。结合现代计算机系统结构的新发展,介绍近几年来计算机系统结构所出现的一些新概念和新技术。 5.数据库概论: 数据库已是计算机系本科生不可缺少的专业基础课,它是计算机应用的重要支柱之一。该课程讲授数据库技术的特点,数据库系统的结构,三种典型数据模型及系统(以关系型系统为主)、数据库规范化理论,数据库的设计与管理,以及数据库技术的新进展等。通过本课程学习,掌握基本概念、理论和方法,学会使用数据库管理系统设计和建立数据库的初步能力,为以后实现一个数据库管理系统及进行系统的理论研究打下基础。 6.算法与数据结构: “数据结构”是计算机程序设计的重要理论技术基础,是计算机科学与技术专业的必修课,是计算机学科其它专业课的先修课程。通过学习本课程使学生掌握数据结构的基本逻辑结构和存储结构及其基本算法的设计方法,并在实际应用中能灵活使用。学会分析研究数据对象的特性,选择合适的逻辑结构、存储结构及设计相应的算法。初步掌握算法的时空分析技巧,同时进行程序设计训练。使学生学会应用抽象数据类型概念进行抽象设计。主要内容有:线性表、链表、栈、队列、数组、广义表、树与二叉树、图、查找、排序、内存管理、文件存储管理。 7.离散数学: “离散数学”是计算机科学与技术专业必修课程,其主要内容包括:命题逻辑;一阶命题逻辑;集合、关系与映射;代数系统、布尔代数 ;图论等。这些内容为学习计算机专业课程,如编译原理、数据结构提供重要的理论工具,同时也是计算机应用不可缺少的理论基础。 离散数学主要培养学生对事物的抽象思维能力和逻辑推理能力,为今后处理离散信息,从事计算机软件的开发和设计,以及计算机的其它实际应用打好数学基础。 8.操作系统: 操作系统是现代计算机系统中不可缺少的重要组成部分。它的先修课程是数据结构和计算机基础,在此基础上讲解操作系统的主要内容:CPU管理、存储器管理、作业管理、I/O设备管理和文件管理。这些基本原理告诉人们作为计算机系统中各种资源的管理者和各种活动的组织者、指挥者,操作系统是如何使整个计算机系统有条不率地高效工作,以及它为用户使用计算机系统提供了哪些便利手段。掌握了这些知识,人们就会对计算机系统的总体框架、工作流程和使用方法有了一个全面的认识,就会清楚后续专业课程所述内容在计算机系统中所处的地位和作用,这样不仅便于理解后续课程内容,而且能使人们把计算机的各部分知识有机地联系起来。此外,由于多处理机系统和计算机网络的盛行,本课程中也包含了对多处理机操作系统和网络操作系统的概述,从而使学习者可以跟上计算机技术的发展速度。 9.数据通信与计算机网: 该课程主要介绍网络基本理论和网络最新实用技术,分基础理论、实用技术和新技术三部分进行讲述。主要讲解计算机网络的功能和组成,数据传输,链路控制,多路复用,差错检测,网络体系结构,网络分层协议及局域网、广域网等。要求学生掌握数据通信的基本原理和计算机网络的体系结构,打下坚实的理论基础,培养实际应用的能力,为今后从事计算机网络的科研和设计工作打下基础。 10.高级语言程序设计: 本课程介绍了C与C++的全集。它从语法入手,同时强调程序设计的基本方法,以使学生能在较短的时间内,掌握C语言的结构化程序设计方法与C++语言的面向对象程序设计方法。主要内容有:1、过程初步;2、过程组织和管理;3、C++的数据类型;4、类与对象;5、继承;6、I/O流。 11.软件工程: 软件工程课程是计算机专业的一门主要专业课程,是培养高水平软件研制和开发人员的一门重程。该课程主要介绍软件工程的概念、原理及典型的方法技术,进述软件生存周期各阶段的任务、过程、方法和工具,讨论了软件工程使用的科学管理技术。 12.数据库应用: 通过实践方式使学生进一步掌握数据库知识和技术,掌握C/S(客户/服务)模式下的大型数据库的设计与实现,培养同行间的合作精神,学习应用合作方法。 13.软件编程实践: 主要介绍最新的常规的软件编程平台、工具和方法。本课程面向应用技术和实用技术,培养学生自学新技术的能力,在WINDOWS下的综合编程能力,实际解决问题能力。 14.计算机网络工程: 计算机技术与通信技术相结合导致了计算机网络的产生。计算机网络已成为当今大型信息系统的基础。-------------------------高等数学、大学英语、概率统计、离散数学、电路、模拟电子、数字电子、数据结构、操作系统、编译原理、计算机网络、数据库原理、软件工程、汇编语言、C++程序设计、接口技术、Java、VC++、计算机病毒分析、信息安全、等。 高数学的是微积分,线性代数,概率论与数理统计。英语是大学英语上下。还有就是专业的计算机知识,数据分析,c语言,java,还有计算机的系统分析,各种软件技术,学会写代码,程序等。

琴瑟 2019-12-02 01:22:34 0 浏览量 回答数 0

问题

【精品问答】Java必备核心知识1000+(附源码)

问问小秘 2019-12-01 22:00:28 870 浏览量 回答数 1

回答

一、基础篇 1.1、Java基础 面向对象的特征:继承、封装和多态 final, finally, finalize 的区别 Exception、Error、运行时异常与一般异常有何异同 请写出5种常见到的runtime exception int 和 Integer 有什么区别,Integer的值缓存范围 包装类,装箱和拆箱 String、StringBuilder、StringBuffer 重载和重写的区别 抽象类和接口有什么区别 说说反射的用途及实现 说说自定义注解的场景及实现 HTTP请求的GET与POST方式的区别 Session与Cookie区别 列出自己常用的JDK包 MVC设计思想 equals与==的区别 hashCode和equals方法的区别与联系 什么是Java序列化和反序列化,如何实现Java序列化?或者请解释Serializable 接口的作用 Object类中常见的方法,为什么wait notify会放在Object里边? Java的平台无关性如何体现出来的 JDK和JRE的区别 Java 8有哪些新特性 1.2、Java常见集合 List 和 Set 区别 Set和hashCode以及equals方法的联系 List 和 Map 区别 Arraylist 与 LinkedList 区别 ArrayList 与 Vector 区别 HashMap 和 Hashtable 的区别 HashSet 和 HashMap 区别 HashMap 和 ConcurrentHashMap 的区别 HashMap 的工作原理及代码实现,什么时候用到红黑树 多线程情况下HashMap死循环的问题 HashMap出现Hash DOS攻击的问题 ConcurrentHashMap 的工作原理及代码实现,如何统计所有的元素个数 手写简单的HashMap 看过那些Java集合类的源码 1.3、进程和线程 线程和进程的概念、并行和并发的概念 创建线程的方式及实现 进程间通信的方式 说说 CountDownLatch、CyclicBarrier 原理和区别 说说 Semaphore 原理 说说 Exchanger 原理 ThreadLocal 原理分析,ThreadLocal为什么会出现OOM,出现的深层次原理 讲讲线程池的实现原理 线程池的几种实现方式 线程的生命周期,状态是如何转移的 可参考:《Java多线程编程核心技术》 1.4、锁机制 说说线程安全问题,什么是线程安全,如何保证线程安全 重入锁的概念,重入锁为什么可以防止死锁 产生死锁的四个条件(互斥、请求与保持、不剥夺、循环等待) 如何检查死锁(通过jConsole检查死锁) volatile 实现原理(禁止指令重排、刷新内存) synchronized 实现原理(对象监视器) synchronized 与 lock 的区别 AQS同步队列 CAS无锁的概念、乐观锁和悲观锁 常见的原子操作类 什么是ABA问题,出现ABA问题JDK是如何解决的 乐观锁的业务场景及实现方式 Java 8并法包下常见的并发类 偏向锁、轻量级锁、重量级锁、自旋锁的概念 可参考:《Java多线程编程核心技术》 1.5、JVM JVM运行时内存区域划分 内存溢出OOM和堆栈溢出SOE的示例及原因、如何排查与解决 如何判断对象是否可以回收或存活 常见的GC回收算法及其含义 常见的JVM性能监控和故障处理工具类:jps、jstat、jmap、jinfo、jconsole等 JVM如何设置参数 JVM性能调优 类加载器、双亲委派模型、一个类的生命周期、类是如何加载到JVM中的 类加载的过程:加载、验证、准备、解析、初始化 强引用、软引用、弱引用、虚引用 Java内存模型JMM 1.6、设计模式 常见的设计模式 设计模式的的六大原则及其含义 常见的单例模式以及各种实现方式的优缺点,哪一种最好,手写常见的单利模式 设计模式在实际场景中的应用 Spring中用到了哪些设计模式 MyBatis中用到了哪些设计模式 你项目中有使用哪些设计模式 说说常用开源框架中设计模式使用分析 动态代理很重要!!! 1.7、数据结构 树(二叉查找树、平衡二叉树、红黑树、B树、B+树) 深度有限算法、广度优先算法 克鲁斯卡尔算法、普林母算法、迪克拉斯算法 什么是一致性Hash及其原理、Hash环问题 常见的排序算法和查找算法:快排、折半查找、堆排序等 1.8、网络/IO基础 BIO、NIO、AIO的概念 什么是长连接和短连接 Http1.0和2.0相比有什么区别,可参考《Http 2.0》 Https的基本概念 三次握手和四次挥手、为什么挥手需要四次 从游览器中输入URL到页面加载的发生了什么?可参考《从输入URL到页面加载发生了什么》 二、数据存储和消息队列 2.1、数据库 MySQL 索引使用的注意事项 DDL、DML、DCL分别指什么 explain命令 left join,right join,inner join 数据库事物ACID(原子性、一致性、隔离性、持久性) 事物的隔离级别(读未提交、读以提交、可重复读、可序列化读) 脏读、幻读、不可重复读 数据库的几大范式 数据库常见的命令 说说分库与分表设计 分库与分表带来的分布式困境与应对之策(如何解决分布式下的分库分表,全局表?) 说说 SQL 优化之道 MySQL遇到的死锁问题、如何排查与解决 存储引擎的 InnoDB与MyISAM区别,优缺点,使用场景 索引类别(B+树索引、全文索引、哈希索引)、索引的原理 什么是自适应哈希索引(AHI) 为什么要用 B+tree作为MySQL索引的数据结构 聚集索引与非聚集索引的区别 遇到过索引失效的情况没,什么时候可能会出现,如何解决 limit 20000 加载很慢怎么解决 如何选择合适的分布式主键方案 选择合适的数据存储方案 常见的几种分布式ID的设计方案 常见的数据库优化方案,在你的项目中数据库如何进行优化的 2.2、Redis Redis 有哪些数据类型,可参考《Redis常见的5种不同的数据类型详解》 Redis 内部结构 Redis 使用场景 Redis 持久化机制,可参考《使用快照和AOF将Redis数据持久化到硬盘中》 Redis 集群方案与实现 Redis 为什么是单线程的? 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级 使用缓存的合理性问题 Redis常见的回收策略 2.3、消息队列 消息队列的使用场景 消息的重发补偿解决思路 消息的幂等性解决思路 消息的堆积解决思路 自己如何实现消息队列 如何保证消息的有序性 三、开源框架和容器 3.1、SSM/Servlet Servlet的生命周期 转发与重定向的区别 BeanFactory 和 ApplicationContext 有什么区别 Spring Bean 的生命周期 Spring IOC 如何实现 Spring中Bean的作用域,默认的是哪一个 说说 Spring AOP、Spring AOP 实现原理 动态代理(CGLib 与 JDK)、优缺点、性能对比、如何选择 Spring 事务实现方式、事务的传播机制、默认的事务类别 Spring 事务底层原理 Spring事务失效(事务嵌套),JDK动态代理给Spring事务埋下的坑,可参考《JDK动态代理给Spring事务埋下的坑!》 如何自定义注解实现功能 Spring MVC 运行流程 Spring MVC 启动流程 Spring 的单例实现原理 Spring 框架中用到了哪些设计模式 Spring 其他产品(Srping Boot、Spring Cloud、Spring Secuirity、Spring Data、Spring AMQP 等) 有没有用到Spring Boot,Spring Boot的认识、原理 MyBatis的原理 可参考《为什么会有Spring》 可参考《为什么会有Spring AOP》 3.2、Netty 为什么选择 Netty 说说业务中,Netty 的使用场景 原生的 NIO 在 JDK 1.7 版本存在 epoll bug 什么是TCP 粘包/拆包 TCP粘包/拆包的解决办法 Netty 线程模型 说说 Netty 的零拷贝 Netty 内部执行流程 Netty 重连实现 3.3、Tomcat Tomcat的基础架构(Server、Service、Connector、Container) Tomcat如何加载Servlet的 Pipeline-Valve机制 可参考:《四张图带你了解Tomcat系统架构!》 四、分布式 4.1、Nginx 请解释什么是C10K问题或者知道什么是C10K问题吗? Nginx简介,可参考《Nginx简介》 正向代理和反向代理. Nginx几种常见的负载均衡策略 Nginx服务器上的Master和Worker进程分别是什么 使用“反向代理服务器”的优点是什么? 4.2、分布式其他 谈谈业务中使用分布式的场景 Session 分布式方案 Session 分布式处理 分布式锁的应用场景、分布式锁的产生原因、基本概念 分布是锁的常见解决方案 分布式事务的常见解决方案 集群与负载均衡的算法与实现 说说分库与分表设计,可参考《数据库分库分表策略的具体实现方案》 分库与分表带来的分布式困境与应对之策 4.3、Dubbo 什么是Dubbo,可参考《Dubbo入门》 什么是RPC、如何实现RPC、RPC 的实现原理,可参考《基于HTTP的RPC实现》 Dubbo中的SPI是什么概念 Dubbo的基本原理、执行流程 五、微服务 5.1、微服务 前后端分离是如何做的? 微服务哪些框架 Spring Could的常见组件有哪些?可参考《Spring Cloud概述》 领域驱动有了解吗?什么是领域驱动模型?充血模型、贫血模型 JWT有了解吗,什么是JWT,可参考《前后端分离利器之JWT》 你怎么理解 RESTful 说说如何设计一个良好的 API 如何理解 RESTful API 的幂等性 如何保证接口的幂等性 说说 CAP 定理、BASE 理论 怎么考虑数据一致性问题 说说最终一致性的实现方案 微服务的优缺点,可参考《微服务批判》 微服务与 SOA 的区别 如何拆分服务、水平分割、垂直分割 如何应对微服务的链式调用异常 如何快速追踪与定位问题 如何保证微服务的安全、认证 5.2、安全问题 如何防范常见的Web攻击、如何方式SQL注入 服务端通信安全攻防 HTTPS原理剖析、降级攻击、HTTP与HTTPS的对比 5.3、性能优化 性能指标有哪些 如何发现性能瓶颈 性能调优的常见手段 说说你在项目中如何进行性能调优 六、其他 6.1、设计能力 说说你在项目中使用过的UML图 你如何考虑组件化、服务化、系统拆分 秒杀场景如何设计 可参考:《秒杀系统的技术挑战、应对策略以及架构设计总结一二!》 6.2、业务工程 说说你的开发流程、如何进行自动化部署的 你和团队是如何沟通的 你如何进行代码评审 说说你对技术与业务的理解 说说你在项目中遇到感觉最难Bug,是如何解决的 介绍一下工作中的一个你认为最有价值的项目,以及在这个过程中的角色、解决的问题、你觉得你们项目还有哪些不足的地方 6.3、软实力 说说你的优缺点、亮点 说说你最近在看什么书、什么博客、在研究什么新技术、再看那些开源项目的源代码 说说你觉得最有意义的技术书籍 工作之余做什么事情、平时是如何学习的,怎样提升自己的能力 说说个人发展方向方面的思考 说说你认为的服务端开发工程师应该具备哪些能力 说说你认为的架构师是什么样的,架构师主要做什么 如何看待加班的问题

徐刘根 2020-03-31 11:22:08 0 浏览量 回答数 0

回答

什么是java反射机制?我们又为什么要学它?当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射。IT行业里这么说,没有反射也就没有框架,现有的框架都是以反射为基础。在实际项目开发中,用的最多的是框架,填的最多的是类,反射这一概念就是将框架和类揉在一起的调和剂。所以,反射才是接触项目开发的敲门砖! 一、Class类什么是Class类?在面向对象的世界里,万事万物皆是对象。而在java语言中,static修饰的东西不是对象,但是它属于类。普通的数据类型不是对象,例如:int a = 5;它不是面向对象,但是它有其包装类 Integer 或者分装类来弥补了它。除了以上两种不是面向对象,其余的包括类也有它的面向对象,类是java.lang.Class的实例化对象(注意Class是大写)。也就是说:Class A{}当我创建了A类,那么类A本身就是一个对象,谁的对象?java.lang.Class的实例对象。那么这个对象又该怎么表示呢?我们先看一下下面这段代码: 1234public class Demo(){F f=new F();}class F{}这里的F的实例化对象就可以用f表达出来。同理F类也是一个实例化对象,Class类的实例化对象。我们可以理解为任何一个类都是Class类的实例化对象,这种实例化对象有三种表示方法: 123456789101112131415public class Demo(){F f=new F();//第一种表达方式Class c1=F.class;//这种表达方式同时也告诉了我们任何一个类都有一个隐含的静态成员变量class//第二种表达方式Class c2=f.getClass();//这种表达方式在已知了该类的对象的情况下通过getClass方法获取//第三种表达方式Class c3 = null;try {c3 = Class.forName("com.text.F");//类的全称} catch (ClassNotFoundException e) {e.printStackTrace();}}class F{}以上三种表达方式,c1,c2,c3都表示了F类的类类型,也就是官方解释的Class Type。那么问题来了: 1System.out.println(c1 == c2)? or System.out.println(c1 == c3)?答案是肯定的,返回值为ture。这表明不论c1 or c2 or c3都代表了F类的类类型,也就是说一个类只可能是Class类的一个实例对象。理解了Class的概念,我们也可以通过类的类类型创建该类的对象实例,用c1 or c2 or c3的newInstance()方法: 12345678910111213Public class Demo1{try {Foo foo = (Foo)c1.newInstance();//foo就表示F类的实例化对象foo.print();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}class F{void print(){}}这里需要注意的是,c1是F类的类类型,创建出来的就是F类的对象。如果a是A类的类类型,那么创建出来的对象也应该与之对应,属于A类的对象。 二、方法的反射Class类有一个最简单的方法,getName(): 1234567891011public class Demo2 {public static void main(String[] args) {Class c1 = int.class;//int 的类类型Class c2 = String.class;//String类的类类型Class c3 = void.class;System.out.println(c1.getName());System.out.println(c2.getName());System.out.println(c2.getSimpleName());System.out.println(c3.getName());}}本的数据类型以及void关键字都是存在类类型的。 案例: 123456789101112131415161718192021222324252627282930313233public class ClassUtil {public static void printClassMethodMessage(Object obj){//要获取类的信息》》首先我们要获取类的类类型Class c = obj.getClass();//我们知道Object类是一切类的父类,所以我们传递的是哪个子类的对象,c就是该子类的类类型。//接下来我们要获取类的名称System.out.println("类的名称是:"+c.getName());/**我们知道,万事万物都是对象,方法也是对象,是谁的对象呢? 在java里面,方法是Method类的对象*一个成员方法就是一个Method的对象,那么Method就封装了对这个成员 *方法的操作*///如果我们要获得所有的方法,可以用getMethods()方法,这个方法获取的是所有的Public的函数,包括父类继承而来的。如果我们要获取所有该类自己声明的方法,就可以用getDeclaredMethods()方法,这个方法是不问访问权限的。Method[] ms = c.getMethods();//c.getDeclaredMethods()//接下来我们拿到这些方法之后干什么?我们就可以获取这些方法的信息,比如方法的名字。//首先我们要循环遍历这些方法for(int i = 0; i < ms.length;i++){//然后可以得到方法的返回值类型的类类型Class returnType = ms[i].getReturnType();//得到方法的返回值类型的名字System.out.print(returnType.getName()+" ");//得到方法的名称System.out.print(ms[i].getName()+"(");//获取参数类型--->得到的是参数列表的类型的类类型Class[] paramTypes = ms[i].getParameterTypes();for (Class class1 : paramTypes) {System.out.print(class1.getName()+",");}System.out.println(")");}}}总结思路:通过方法的反射得到该类的名称步骤:1.获取该类的类类型2.通过类类型获取类的方法(getMethods())3.循环遍历所获取到的方法4.通过这些方法的getReturnType()得到返回值类型的类类型,又通过该类类型得到返回值类型的名字5.getName()得到方法的名称,getParameterTypes()获取这个方法里面的参数类型的类类型。 三、成员变量的反射首先我们需要认识到成员变量也是对象,是java.lang.reflect.Field类的对象,那么也就是说Field类封装了关于成员变量的操作。既然它封装了成员变量,我们又该如何获取这些成员变量呢?它有这么一个方法: 12345public class ClassUtil {public static void printFieldMessage(Object obj){Class c = obj.getClass();//Field[] fs = c.getFields();}这里的getFields()方法获取的所有的public的成员变量的信息。和方法的反射那里public的成员变量,也有一个获取所有自己声明的成员变量的信息:Field[] fs = c.getDeclaredFields(); 我们得到它之后,可以进行遍历(既然封装了Field的信息,那么我们就可以得到Field类型) 12345678for (Field field : fs) {//得到成员变量的类型的类类型Class fieldType = field.getType();String typeName = fieldType.getName();//得到成员变量的名称String fieldName = field.getName();System.out.println(typeName+" "+fieldName);}四、构造函数的反射不论是方法的反射、成员变量的反射、构造函数的反射,我们只需要知道:要想获取类的信息,首先得获取类的类类型。 12345678910111213141516171819202122public static void printConMessage(Object obj){Class c = obj.getClass();/* 首先构造函数也是对象,是java.lang.Constructor类的对象 也就是java.lang. Constructor中封装了构造函数的信息 和前面说到的一样,它也有两个方法: getConstructors()方法获取所有的public的构造函数 getDeclaredConstructors()方法得到所有的自己声明的构造函数*/ //Constructor[] cs = c.getConstructors();Constructor[] cs = c.getDeclaredConstructors();for (Constructor constructor : cs) {//我们知道构造方法是没有返回值类型的,但是我们可以:System.out.print(constructor.getName()+"(");//获取构造函数的参数列表》》得到的是参数列表的类类型Class[] paramTypes = constructor.getParameterTypes();for (Class class1 : paramTypes) {System.out.print(class1.getName()+",");}System.out.println(")");}}五、Class类的动态加载类如何动态加载一个类呢?首先我们需要区分什么是动态加载?什么是静态加载?我们普遍认为编译时刻加载的类是静态加载类,运行时刻加载的类是动态加载类。我们举一个例子: 123456789101112Class A{Public static void main(String[] args){if("B".equal(args[0])){B b=new B();b.start();}if("C".equal(args[0])){C c=new C();C.start();}}}上面这一段代码,当我们在用eclipse或者myeclipse的时候我们并不关心是否能够通过编译,当我们直接在cmd使用javac访问A.java类的时候,就会抛出问题: 1234567891011121314151617A.java:7:错误:找不到符号B b=new B();符号: 类B位置: 类AA.java:7:错误:找不到符号B b=new B();符号: 类B位置: 类AA.java:12:错误:找不到符号C c=new C();符号: 类C位置: 类AA.java:12:错误:找不到符号C c=new C();符号: 类C位置: 类A4个错误或许我们理所当然的认为这样应该是错,类B根本就不存在。但是如果我们多思考一下,就会发现B一定用吗?不一定。C一定用吗?也不一定。那么好,现在我们就让B类存在 12345Class B{Public static void start(){System.out.print("B...satrt");}}现在我们就先 javac B.class,让B类先开始编译。然后在运行javac A.class。结果是: 123456789A.java:12:错误:找不到符号C c=new C();符号: 类C位置: 类AA.java:12:错误:找不到符号C c=new C();符号: 类C位置: 类A2个错误我们再想,这个程序有什么问题。如果你说没有什么问题?C类本来就不存在啊!那么问题来了B类已经存在了,假设我现在就想用B,我们这个程序用得了吗?答案是肯定的,用不了。那用不了的原因是什么?因为我们这个程序是做的类的静态加载,也就是说new创建对象是静态加载类,在编译时刻就需要加载所有的,可能使用到的类。所以不管你用不用这个类。现在B类是存在的,但是我们这个程序仍然用不了,因为会一直报C类有问题,所以B类我也用不了。那么在实际应用当中,我们肯定需要如果B类存在,B类我就能用,当用C类的时候,你再告诉我错了。如果说将来你有100个类,只要其中一个类出现问题,其它99个类你都用不了。所以这并不是我们想要的。我们想要的就是我用那个类就加载那个类,也就是常说的运行时刻加载,动态加载类。如何实现动态加载类呢?我们可以建这么一个类: 1234567891011Class All{Public static void start(){try{Class cl= Class.forName(args[0]);//通过类类型,创建该类的对象cl.newInstance();}catch(Exception e){e.printStackTrace();}}}前面我们在分析Class实例化对象的方式的时候,Class.forName(“类的全称”),它不仅仅表示了类的类类型,还表示了动态加载类。当我们javac All.java的时候,它不会报任何错误,也就是说在编译的时候是没有错误的。只有当我们具体用某个类的时候,那个类不存在,它才会报错。如果加载的类是B类,就需要: 1B bt = (B) cl.newInstance();万一加载的是C类呢,可以改成 1C ct = (C) cl.newInstance();但是如果我想用很多的类或者加载很多的类,该怎么办?我们可以统一一个标准,不论C类还是B类或者其他的类,比如定义一个标准 1Stand s = (Stand) cl.newInstance();只要B类和C类都是这个标准的就行了。 123456789101112131415Class All{Public static void start(){try{Class cl= Class.forName(args[0]);//通过类类型,创建该类的对象Stand s = (Stand) cl.newInstance();s.start();}catch(Exception e){e.printStackTrace();}}}interface Stand {Public void start();}现在如果我想要用B类,我们只需要: 12345Class B implements Stand{Public void start(){System.out.print("B...satrt");}}加载B类,编译运行。 123javac B.javajavac Stand.javajava Stand B结果: 1B...satrt如果以后想用某一个类,不需要重新编译,只需要实现这个标准的接口即可。只需要动态的加载新的东西就行了。这就是动态加载类。

auto_answer 2019-12-02 01:50:24 0 浏览量 回答数 0

问题

【精品问答】python技术1000问(2)

问问小秘 2019-12-01 22:03:02 68 浏览量 回答数 0

问题

【精品问答】python技术1000问(1)

问问小秘 2019-12-01 21:57:48 448858 浏览量 回答数 12
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播