0、servlet:用java编写的服务器终端,可以生成动态的web页面
生命周期:
初始化阶段 init():当servlet被第一次请求时会调用这个方法来初始化一个servlet对象出来(只有第一次才会调用这个方法)
响应阶段 service():每当请求servlet时,容器就会调用这个方法
终止阶段 distory():当要销毁servlet时,会调用这个方法
web服务器与客户端交互时servlet的工作流程:客户端对web发出请求
web服务器接收到请求将其发送给Servlet
Servlet容器为此产生一个实例对象并处理响应结果,返回给web服务器
web服务器从实例对象中收到响应结构发回客户端
最后,Servlet由JVM的垃圾回收器进行垃圾回收
1、JVM
jvm的内存结构:
程序计数器
虚拟机栈
本地方法栈
前三个区域随线程而生,随线程而死,当线程结束时内存就会被回收。
堆区
方法区
后两者的内存的分配和回收是动态的,在垃圾回收前需要判断对象是否存活。
引用计数算法:
堆中每个对象实例都有一个引用计数,当一个对象被创建时,就将该对象的实例分配给一个变量,该变量计数设置为1,当被引用时计数加1
当对象超过了生命周期就减1,引用计数为0的对象就可以被回收,当循环引用时就会出现问题,引用计数不可能为0 如父、子对象相互引用。
可达性分析算法:
把引用关系看做一张图,从一个结点GC root开始,寻找对应的引用节点,找到这个节点之后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,
剩下的节点就是无用的节点 就是可回收的对象。
可作为GC Root的对象:
虚拟机栈中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中,JNI(即一般说的Native方法)引用的对象。
java中的引用(判断存活的两种方式与引用有关):
强引用:只要强引用再,就不回收。
软引用:SoftReference 类实现软引用。在系统要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行二次回收。
弱引用:WeakReference 类实现弱引用。对象只能生存到下一次垃圾收集之前。在垃圾收集器工作时,无论内存是否足够都会回收掉只被弱引用关联的对象。
虚引用:PhantomReference 类实现虚引用。无法通过虚引用获取一个对象的实例,为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
垃圾回收:
2、jdbc
根本上说JDBC是一种规范,它提供的接口,一套完整的,允许便捷式访问数据库
3、jsp
是javaweb服务器端的动态资源,它与html页面的作用是相同的,显示数据和获取数据
是请求的发起页面
jsp=html+java脚本+jsp标签
九大内置对象:
PageContext:最重要的一个对象,代表jsp的运行环境这个对象不仅封装了对其他8大隐式对象的引用,自身还是一个域对象,可以用来保存数据。
这个对象还封装了web开发中经常涉及的一些常用操作,比如引用和跳转其他资源,检索其他域对象中的属性。
request:封装了由客户端生成的http请求的所有细节,主要包括http头信息,系统信息,请求方式和请求参数。
response:用于响应客户请求,向客户输出信息。它封装了JSP产生的响应,并发送到客户端以响应客户端的请求
session:在网络中称为会话。当客户向服务器发送请求,服务器接收请求并返回响应后,该连接就结束了。为了弥补这一缺点,http协议提供了session
可以在web页面间进行跳转时保存用户的状态,直达关闭浏览器这一会话才会消失。
application:
config
out:用于向客户端发送文本数据,通过调用pageContext对象的getOut方法返回的
page:可以理解为一个对象本身,几乎不用可以了解一下。
exception
4、javascript
开发web页面的脚本语言
Jquery:是一个javascript库
5、Ajax(是一种思想)
Asynchronous Javascript and XML 的简称,简单来说,就是通过XMLHttpRequest对象向服务器发送异步请求,获取数据后,再通过js来操作DOM节点。
6、jquery
7、Bootstrap
8、Spring
spring概念:Spring是个轻量级java企业级应用的开源开发框架。
Spring有哪些模块:
Spring Core:核心类库,提供IOC服务。所有的功能都依赖于该库
Sprign Context:提供框架式的Bean访问,
Spring Aop:提供了AOP拦截机制,提供常用的拦截器,供用户自定义和配置
Spring Dao:对jdbc的抽象,简化了数据访问异常的处理
Spring Orm:对象关系映射
Spring web:提供了面向web的一些特性
Spring MVC:提供面向web的model-view-controller实现
ioc 也就是我们常说的控制反转 ,是一种设计思想 是spring的核心 ,意味着将你设计好的对象交给容器控制,而不是传统的
再你的对象的内部直接控制。为什么叫控制反转呢 我觉得对于spring框架来说就是由spring来控制对象的生命周期和对象之间的关系
所有的类都会在容器中登记,当用到的时候spring就会给你,也就是说控制对象的生命周期不再是对象 而是spring控制
ioc的两种配置方法:
bean
xml
di
就比如A对象需要操作数据库,就需要自己动手去创建
connection对象 然而spring的话就不需要 当他发现你需要connection对象的时候会自动创建一个注入到A中,
注入依赖的方式有几种:
1、构造器注入
2、setter方法注入
3、接口注入
Aop:Aspect oriented Programing 的缩写,意为面向切面编程,代理模式的典型应用,将程序抽象成各个切面,对象和对象之间,类和类之间,层和层之间都可以理解为切面。为解耦而生。这种思想的技术支撑是动态代理,
解决了大量的代码重复。
Aop要达到的效果:保证开发者不修改源代码的前提下,去为系统中的业务组件添加功能。
为什么要使用动态代理:
在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和代理对象之间起到中介作用,特征就是
代理类和委托类有同样的接口。
Autowired和resource关键字的区别:
都是做bean注入时使用,两者都可以写在字段和setter方法之上,两者如果都写在字段之上。
Autowired:根据类型注入
Resource:默认根据名字注入,
9、SpringMvc
mvc三层:
模型层:表示数据和业务处理。
视图层:用户看到与之交互的页面
控制器层:接收用户的输入,并调用模型和视图去完成用户的请求。
Requestmapping:处理url映射的注解,用于类或者方法之上
requestbody:接收jison数据将jison转化为java对象
responsebody:将controller方法返回对象转化为jison对象响应给客户
controller:用于控制器层
Autowired和Resource都是bean的注入时使用。
如何设定重定向和转发:
转发:再返回值前面加“forward”比如forward:控制器的mapping参数
重定向:再返回值前面加“redirect”。
10、Springboot
springboot的特性:基于spring的开发提供更快的入门体验
springboot的核心注解:@SpringbootApplication(核心注解)
@SpringBootConfiguration 实现配置文件的功能
@EnableAutoConfiguration 打开自动配置的功能
@ComponentScan Spring组件扫描
11、SpringData
12、MyBatis
12、oracle 常用的命令:
show name from 文件的位置、数据库的名字
管理用户:
alter 修改
create user 。。。创建用户
权限的授予:grant create session to zhangsan;//授予zhangsan用户创建session的权限
grant create table to zhangsan;//授予创建表的权限
grante drop table to zhangsan;//授予删除表的权限
grant insert table to zhangsan;//插入表的权限
grant update table to zhangsan;//修改表的权限
13、Mybatis-plus
14、SSM
15、SpringSecurity
16、Elasticsearch
17、SpringBoot-Redis
18、RabbitMQ
19、SpringCloud
Eurka:注册中心 基于REST的服务,用于定位服务。以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务来说非常重要,有了服务发现和注册,只要用服务的标识符,就可以访问到服务。
就不需要修改服务调用的配置文件了,功能类似于Dubbo的注册中心zookeeper
gateway:网关:
Ribbon:负载均衡(Load Balance):主要功能是提供客户端的软件负载均衡算法,Ribbon的客户端组件提供一系列完整的配置项:如连接超时,重试等等。
Ribbon会帮助你基于某种规则(轮询或者随机)去连接这些机器。可以很容易的用Ribbon实现负载均衡。
常见的负载均衡的软件:Nginx,Lvs等等;
作用:简单地说就是将用户的请求平摊的分配到多个服务上,从而达到系统的高可用。
负载均衡的简单分类:
集中式LB:即再消费方和提供者之间使用独立的负载均衡设施,如Nginx:反向代理服务器! 将访问请求通过某种策略转发至服务器的提供方。
进程式LB:将负载均衡的逻辑集成到消费方,消费方从服务中心获知有哪些地址可用,然后再从这些地址中选出一个合适的服务器。比如Ribbon
feign:访问远程服务,一个服务调用另外一个服务的api,让微服务之间的调用变得更简单了。类似于controller调用service。
再Feign的实现下,我们只需要创建一个接口并使用注解来配置它。主要有两个依赖:@EnableFeignClients:用于开启feign功能;@FeignClinent:定义feign接口。
20、SpringDubbo
22、Docker
23、数据库的区别
关系型数据库:mysql、oracle
非关系型数据库:redis、MongoDB
24、mybatise和plus的区别
25、
进程:
程序运行时,CPU会为其分配内存空间,程序的运行就是进程
线程:
线程是程序执行时的最小单位,一个程序就是一个进程,一个程序可以有多个线程,
创建进程的3种方法:
继承thread类
实现runabel接口
实现CallAble接口
线程的生命周期
新建:new thread
就绪:start()
运行:run()
阻塞:sleep()
死亡:线程完成任务或者终止条件发生
wait和sleep的区别:
sleep:thread类中的方法,使程序暂停执行指定的时间,让cpu让出该线程,但它的监控状态依然保持。当指定的时间到了又会自动恢复运行状态,不会释放对象锁。
wait:属于Object类中的方法,会在线程休眠的同时释放掉机锁,其他线程就可以访问该对象。
多线程
操作系统能够运算调度的最小单位
对于单核CPU来说:多线程就是一个CPU在来回切换,交替执行。
对于多核CPU来说:多线程就是同时有多条线程在执行,每个核执行一个线程,有可能一块同时执行。
26、集合
List遍历方式:
1、for循环遍历:fot(int i ; i
3、迭代器 iterator :
ArrayList
list.add(new News(1,"list1","a"));
list.add(new News(2,"list2","b"));
Iterator
while (iter.hasNext()) {
News s = (News) iter.next();
System.out.println(s.getId()+" "+s.getTitle()+" "+s.getAuthor());
}
linkdlist和arraylist的区别
linkdlist:基于链表的 基于链表的数据结构,地址是任意的,对于新增和删除操作add和remove,LinedList比较占优势。
arraylist:基于动态数组 因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。
对于随机访问get和set ArrayList要优于linkedList 因为linkedList需要移动指针 但是删除和增加的话 linkedList好,因为ArrayList如果要删除第一条数据那么第二条以后的都需要往前移。
集合和数组的区别:长度数组不可变集合可变,内容数组可以是基本类型,也可以是引用类型而集合只能是引用类型;元素内容,数组只能存储同一种类型,集合可以存储不同类型(建议同一种)
链表:我们知道物理存储结构只有两种:分为顺序存储和链式存储,
概念:是由数据域和指针域组成,数据域就是用来存储数据,指针域就是指针,用来标记此数据的相邻位置的数据。数据域加指针域就是一个结点,N个结点就是一个链表。
collection
list(有序,可重复)
set(无序,不能包含重复元素)
queue
map(键值对,键唯一,值不唯一)
如何遍历map
遍历map中的键
for (Integer key : map.keySet()) {
System.out.println("Key = " + key);
}
遍历map中的值
for (Integer value : map.values()) {
System.out.println("Value = " + value);
Hashcode的作用:
java的集合有两类,一类是List,一类是Set,前者有序可重复,后者无序不重复,当我们在set中插入的时候怎么判断是否已经存在该元素呢,可以通过equals方法。但是如果元素太多,
用这样的方法就会比较慢。于是有人发明了哈希算法来提高集合中查找元素的效率。 这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,
每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的那个区域。 hashCode方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,
当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;
如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大降低了,
几乎只需要一两次。
HashMap:一个用于存储key-value键值对的集合。底层实现是数组+链表(当链表长度大于8时转换为红黑树)+红黑树(jdk8之后引入)
相比其他数据结构,在哈希表中进行添加,删除,查找等操作,性能很高,不考虑哈希冲突的情况下,一次定位就可以完成。
Hashmap的存储结构:java之前是Entry
HashMap的实现原理:我们知道数据结构的物理存储结构只有两种,顺序存储结构和链式存储结构,在数组中根据下标查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干就是
数组。比如我们要新增或查找某个元素,我们通过把当前元素的关键字通过Hashcode函数映射到数组中的某个位置,通过数组下标一次定位就可以完成。
哈希冲突:如果两个不同的元素,通过哈希函数得出的实际存储地址相同 发现被其他元素占用,也叫哈希碰撞。
哈希函数的设计很重要,因为数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突,要解决这个问题就需要加链表,如果定位到的数组位置
不含链表,那么查找和添加的操作一次寻址就可以,如果定位到的数组包含链表,首先遍历链表,存在即覆盖,否则新增。对于查找来说,仍需遍历链表,链表越少性能越好。
27、MVVM
28、线程池
谈谈你对线程池的理解:由任务队列和工作线程组成,我认为就是一个容器里面放置了很多线程,再任务过多时通过排队避免创建过多线程减少系统资源消耗,这里涉及到两个概念
一个是核心线程数(corePoolSize) :它会一直存在,即使没有任务需要执行。当线程数小于核心线程数时,这时有新的任务提交那么线程池也会优先创建新的线程
当核心线程数达到最大时,新的任务会放在队列中等待执行,当不断有新的任务进来,队列也满了的时候就会涉及到最大线程数(maxPoolSize),当线程数大于核心线程数小于最大线程数的时候
且队列排满了,那么线程池还会创建新的线程来执行新的任务,当线程数达到最大线程数的时候,那么线程池会拒绝处理任务并抛出异常。它的工作原理就是这个样子。
29、反射
什么是反射:
在运行状态中,对于任何一个类,都能知道这个类的所有属性和方法。对于任意一个类都可以调用他的任意一个方法和属性。
30、IO流
流的分类:
按照流向:输入流、输出流
操作单元:字节流(继承inputstream和outputstream)、字符流(继承reader和writer)
设计模式:基础流、包装流
来源分类:文件流、内存流、网络流、控制台流
谈谈javaIO的常见类:
输入流:输入流就是从外部文件输入到内存,输出流就是从内存输出到文件。
字符流中有抽象类:inputstream和outputstream他们的子类fileinputstream、fileoutputstream、bufferedoutputstream,
字符流bufferedreader和bufferedwriter
阻塞方法:是指程序调用该方法时,必须等待输入数据可用或者检测到输入结束或者抛出异常,否则程序会一直停留在该语句上,不会执行下面
的语句。比如read()的readLine()方法。
字符流和字节流的区别:
在应用中经常会有一段文本输出去或者读进来,计算机只识别二进制字节,当有一串字符要输出时,就需要将其转换成字节,
字符流是字节流的包装,字符流则是直接接收字符串
31、equals和==的区别
==:比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同。即是否是指相同一个对象,比较的是指针意义上的
操作。
equals:用来比较两个对象的内容是否相等,由于都是继承object类,所以适用于所有对象】 s1.equals(s2)。
32、String、StringBuffer、StringBuilder
String:是java中很重要的一个类,被final修饰。每次对string操作都会生成新的String对象,例如拼接字符串的时候会产生很多无用的中间对象,如果频繁的操作就会影响程序的性能。
StringBuffer(jdk1.0):就是用来解决拼接大量字符串时产生的很多中间对象问题而提供的一个类。提供append和add方法可以将字符串添加到已有
序列的末尾或者指定位置。而且是线程安全的。
StringBuilder(jdk1.5):本质上和StringBuffer一样,但是去掉了线程安全的那部分。
StringBuffer和StringBuilder都继承了AbstractStringBuilder,底层都是利用可修改的char数组。
33、重写和重载的区别
重写(override):从字面上看就是重新写一遍的意思,就是在子类中把父类本身有的方法重新写一遍,子类继承了父类原有的方法,但子类不想原封不动的继承
父类的某个方法,所以在方法名、参数列表、返回类型都相同的情况下,对方法进行修改或重写。
重载(overload):在一个类中,同名的方法如果有不同的参数列表,则视为重载。
34、cookie和session的区别:
cookie:实际上是一小段的文本信息,客户端请求服务器,如果服务器需要记录该用户的状态,就用response向客户端浏览器颁发一个cookie。客户端会把cookie存起来。
服务器也可以根据需要修改cookie的内容。比如cookie的失效日期(最好不要把敏感的、未加密的数据放在cookie中否则会影响网站的安全)
session:是另一种记录客户端状态的机制,不同的是cookie保存在客户端浏览器中,而session保存在服务器上,客户端浏览器访问服务器的时候,
服务端会把客户端的信息以某种形式记录再服务器上。
二者的区别:数据存储位置: cookie存放在客户的浏览器上,session放在服务器上。
安全性:如果考虑安全性的话用session
cokkie保存的数据不能超过4k,很多浏览器最多保存20个cookie。
35、消息队列
是分布式系统中的重要组件,主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性架构,
ActiveMQ、RabbitMQ、kafka、RocketMQ、ZeroMQ
优点: 解耦:当请求发生时,A系统可能调用B、C、D系统任何一个执行过程出问题都会导致请求结果失败。所以这时候用MQ解耦就很重要。
异步:使用MQ还会带来另一个好处就是异步,很大程度上提高用户的使用体感。
流量削峰:比如秒杀商城,数据库会涌入大量的数据很有可能被压垮,这时候就需要MQ,比如设定A系统每秒从MQ中拉取2k个请求。。。
流量削峰的经济考量价值:业务系统的正常时段的QPS(每秒请求事务的数量)如果是1000,最高峰是10000,要按1000+削峰来配而不是
而不是应对流量高峰配置高性能服务器(性能的浪费)
缺点: 系统可用性降低
系统复杂度提高
一致性问题
36、mysql
数据库的三范式:1:字段具有原子性,不可再分
2:每个实例或行必须可以唯一的被区分
3:每个表不能包含其他表已经包含的非主关键字信息
常用的索引有哪些:
普通索引:对数据库表创建索引
唯一索引:索引列的值必须唯一,允许有空值
主键索引:特殊的唯一索引,不允许有空值。一般在建表的时候同时创建主键索引。
组合索引:多个字段联合起来作为一个组合索引,效率更高。
varchar与char的区别varchar(50)50代表的含义:
char:是一种固定长度的类型
varchar:是一种可变长度的类型
50:最多放50个字节
int(20)20代表最大显示宽度
mysql中Innodb支持的4种事务隔离级别
Read Uncommitted(读取未提交内容):也叫脏读,很少实际应用,性能也不是很好。
Read Committed(读取提交内容):一个事务只能看见已经提交事务所做的改变。
Repeatable Read(可重读):mysql默认的事务隔离级别,会产生幻读问题,
Serializable(可串行化):最高的隔离级别,通过强制事务排序,从而解决幻读问题。
索引的工作机制:
是数据库管理系统中一个排序的数据结构,用来快速查询和更新数据。
索引的实现:
通常是B树和B+树
37、mysql和Oracle的区别
1、对事物的提交:mysql是默认提交,oracle默认不自动提交,需要手动提交,写commit指令。
2、分页查询:mysql 直接再sql语句中写limit就行,而oracle则需要用到伪列rownum和嵌套查询
3、事务隔离级别:oracle:read commited (读取并提交),mysql是 repeatable read(可重复读)二者都支持串行化事务隔离级别
4、最重要的区别: MySQL是轻量型数据库,并且免费,没有服务恢复数据。
Oracle是重量型数据库,收费,Oracle公司对Oracle数据库有任何服务。
38、Linux常用命令:
1、基本命令:
关机:shutdown -h now 立刻关机
shotdown -h 5 5分钟后关机
poweroff 立刻关机
重启:shutdown -r now 立刻重启
shotdown -r 5 5分钟后重启
reboot 立刻重启
帮助命令:-help
2、目录操作命令:
目录切换:cd
目录查看:ls
创建目录:mkdir
删除目录:rm
重命名目录:cp-r
搜索目录:find
3、文件操作命令:
新建文件:touch
删除文件:rm
修改文件:vi
编辑模式:insert
复制文件:cp
退出: q q!wq
打开文件:vi 文件名
编辑文件:i、a、o
取消编辑:esc
保存退出:wq
4、压缩文件操作:
5、查找命令:
查找服务进程:grep
查找文件:find
6、监控linux的系统状况cpu、内存的使用情况:top
7、切换用户:su 用户名
39、#和$的区别
sql注入:用于攻击数据驱动的应用,恶意的sql语句在表单或URL上输入一些sql片段,有的参数检验不足的应用程序就可能被攻击,
#:相当于JDBC SQL 语句中的占位符,将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,如果传入的值是111,那么解析成sql时的值为order by“111”
可以很大程度上防止sql注入
$:相当于JDBC SQL 的连接符,将传入的数据直接显示生成再sql中。如order by ${id} 会解析成order by id 这样的话就无法防止sql注入。一般用于穿入数据库对象,
例如穿入表名。
一般尽量用#
mybatise用order by 动态参数时要注意用$而不是#。
40、ioc的两种配置方式:
41、跨域问题
同源策略:
它是浏览器最核心也是最基本的安全功能,即协议,域名,端口号都相同。
跨域解决办法:
1、response添加header : resp.setHeader("Access-Control-Allow-Origin", "*") (*代表支持所有网站的访问)
2、JSONP方式:
42、单例模式:是一种常用的软件设计模式,其定义的类只允许一个实例存在。
优点:1、内存中只有一个对象节省内存空间。
2、避免频繁的创建销毁对象,提高性能。
3、避免对共享资源的多重占用,简化访问。
4、为整个系统提供一个全局访问点。
缺点:
1、不适合用于变化频繁的对象。
2、可能会导致共享连接池对象的程序过多而出现连接池溢出。
3、如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失。
实现方式:
饿汉式:
// 饿汉式单例
public class Singleton1 {
// 指向自己实例的私有静态引用,主动创建
private static Singleton1 singleton1 = new Singleton1();
// 私有的构造方法
private Singleton1(){}
// 以自己实例为返回值的静态的公有方法,静态工厂方法
public static Singleton1 getSingleton1(){
return singleton1;
}
}
懒汉式:// 懒汉式单例
public class Singleton2 {
// 指向自己实例的私有静态引用
private static Singleton2 singleton2;
// 私有的构造方法
private Singleton2(){}
// 以自己实例为返回值的静态的公有方法,静态工厂方法
public static Singleton2 getSingleton2(){
// 被动创建,在真正需要使用时才去创建
if (singleton2 == null) {
singleton2 = new Singleton2();
}
return singleton2;
}
}
双重加锁机制:
public class Singleton
{
private static Singleton instance;
//程序运行时创建一个静态只读的进程辅助对象
private static readonly object syncRoot = new object();
private Singleton() { }
public static Singleton GetInstance()
{
//先判断是否存在,不存在再加锁处理
if (instance == null)
{
//在同一个时刻加了锁的那部分程序只有一个线程可以进入
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
静态初始化:
//阻止发生派生,而派生可能会增加实例
public sealed class Singleton
{
//在第一次引用类的任何成员时创建实例,公共语言运行库负责处理变量初始化
private static readonly Singleton instance=new Singleton();
private Singleton() { }
public static Singleton GetInstance()
{
return instance;
}
}
43、面向对象和面向过程的区别:
面向过程:分析出问题所需要的步骤,然后用函数一步一步实现,使用时依次调用就可以了,
优点:性能比较好,因为类调用时需要实例化,比较消耗资源,比如linux就采用面向过程开发的。
缺点:不易维护。
面线对象:把构成问题的事务分解成各个对象,
优点:易维护,易扩展。
缺点:性能比较低
44、逆向工程:



