1. 实现删除一个数组里面的重复值?
使用键值反转
array_flip();<?php$a1=array("a"=>"red","b"=>"green","c"=>"blue","d"=>"yellow");$result=array_flip($a1);print_r($result);?>
function unique3(array){ var n = [array[0]];//结果数组 //从第二项开始遍历 for(var i = 1; i<array.length; i++){ //如果当前数组的第i项在当前数组中第一次出现的位置不是i; //那么表示第i项是重复的,忽略掉。否则存入结果数组。 if(array.indexOf(array[i]) == i){ n.push(array[i]); } } return n;}
2.什么是redis?
开源 先进的key-value存储
远程字典服务器 内存级数据库 数据结构服务器
一个基于内存的网络存储系统
3.redis数据类型有哪几种?
值(value)可以是:字符串(String),
哈希(hash),
列表(list),
集合(sets)
有序集合(sorted sets)
4.redis持久化是如何操作的?
为了保证效率数据都缓存在内存中,可以周期性写入磁盘或者把修改操作写入文件(持久化)。
5.redis适应的一些场景
1、取最新 N 个数据的操作 2、排行榜应用,取 TOP N 操作 3、需要精准设定过期时间的应用 4、计数器应用 5、Uniq 操作,获取某段时间所有数据排重值 6、实时系统,反垃圾系统 7、Pub/Sub 构建实时消息系统 8、构建队列系统 9、缓存
6.redis的三个特点?
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。- Redis支持数据的备份,即master-slave模式的数据备份。
7.ECS与虚拟主机的区别介绍
一个是服务器 一个相当于是服务器里的文件夹 云主机是在集群服务器上划分出来的独立的内存.硬盘.带宽等资源搭建而成的 一个虚拟服务器.有独立的IP和带宽,可以根据需求安装各版本操作系统以及 配置各种网站运行环境,有远程桌面连接东西.是完全独立的. 而虚拟主机是在服务器硬盘上划分出来的一部分存储空间,它共享的是服务器 的IP和带宽.没有独立的资源和独立的操作系统.没有远程桌面功能,通常虚拟主机所支持的网站程序也是默认分配好的.没有办法由用户自己配置环境.功能相对单一.
8. 重启redis
service redis-server restart
9. 有序集合是怎么排序的?
它给集合中的每一个元素设置分数,按照其分数进行排序,也不允许有重复值
10.谈谈你对memcache的理解
免费并且开源,高性能的,分布式的内存对象缓存系统 数据形态以key->value结构 用于从数据库调用、API调用或页面呈现的结果中获得少量任意数据(字符串、对象)。
11. 谈谈你对redis的理解
- 开源 先进的key-value存储- 远程字典服务器 内存级数据库 数据结构服务器 - 一个基于内存的网络存储系统五种数据类型 字符串(String), 哈希(hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)三个特点: Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存 储。 Redis支持数据的备份,即master-slave模式的数据备份。应用场景: 1、取最新 N 个数据的操作 2、排行榜应用,取 TOP N 操作 3、需要精准设定过期时间的应用 4、计数器应用 5、Uniq 操作,获取某段时间所有数据排重值 6、实时系统,反垃圾系统 7、Pub/Sub 构建实时消息系统 8、构建队列系统 9、缓存
12. memcached与redis的区别
两者对比: redis提供数据持久化功能,memcached无持久化; redis的数据结构比memcached要丰富,能完成场景以外的事情; memcached的单个key限制在250B,value限制在1MB;redis的K、V都为512MB;当然这些值可以在源码中修改; memcached数据回收基于LRU算法,Redis提供了多种回收策略(包含LRU),但是redis的回收策的过期逻辑不可依赖,没法根据是否存在一个key判断是否过期。但是可根据ttl返回值判断是否过期; memcached使用多线程,而redis使用单线程,基于IO多路复用实现高速访问。所以可以理解为在极端情况下memcached的吞吐大于redis。 结论: 普通KV场景:memcached、redis都可以。 从功能模块单一这个角度考虑的话,推荐memcached,只做cache一件事。 在KV长度偏大、数据结构复杂(比如取某个value的一段数据)、需要持久化的情况下,用redis更适合:但是在使用redis的时候单个请求的阻塞会导致后续请求的积压,需要注意
13. 缓存的原理
有缓存则读缓存,没缓存则读数据库然后做缓存
14. memcache和memcached的区别
memcached是php连接memcached服务器的php扩展它的名字就叫memcached 以前有个叫memcache也是php连接memcached服务器的扩展,它的名字叫memcache php的memcache和memcached扩展都是作为客户端去连接memcached服务器 但memcached作为客户端比memcache性能更好功能更强大,而且memcache已经停止更新了,因此现在使用扩展的 话就用memcached
15. 存放session的三种方法
1、如果你能修改到服务器配置文件,那就打开打开php.ini 修改下面两项: session.save_handler = memcache session.save_path = "tcp://127.0.0.1:11211" 2、修改网站根目录下的.htaccess文件 php_value session.save_handler "memcache" php_value session.save_path "tcp://127.0.0.1:11211" 3、最常用的方法 在程序代码中修改(推荐) ini_set("session.save_handler", "memcache"); ini_set("session.save_path", "tcp://127.0.0.1:11211");
16. mysql优化的一般步骤?
1. sql及索引 索引优化 开启慢查询日志 分析sql语句 分析是否加上索引 分析是否用上索引 2. 数据库表结构 3.系统配置 3. 优化计算机硬件
17. 对mysql事物的理解?
是多个步骤为一个过程的事务(整体) 1. 事务使用 INNODB 数据库引擎 如果你不是INNODB ,开启事务,删除那就真的删除了. 2. 要么成批的sql全部执行,要么不执行 3. 事务用来管理 insert update delete 的语句 事务条件: 原子性 一组事务,要么成功,要么撤回. 稳定性 有非法数据(外键约束),事务撤回 隔离性 事务独立运行. 一个事务,处理后的结果影响到了其他事务,则事务撤回! 可靠性 软件或者硬件崩溃,Innodb 表驱动,会利用日志文件,重构修改. 可靠 性 高速度 不可兼得 关键字: Commit 提交 当一个事务完成后,发出commit 命令使所有的参与表 完成更改. Rollback 回滚 如果发送故障,发出rollback命令 使事务返回到 所有表以前的状态. 语句: set autocommit = 0; sql操作 savepoint p1; sql操作 savepoint p2; sql操作 ROLLBACK to p2; commit;
18. mysql触发器是什么?
监视某种事件,并触发某种操作(商品的添加,订单的删除 等等 连贯操作时候使用)
###触发四要素 1. 监视地点 table 2. 触发时间 (after/ before) 3. 监视事件 (insert/update/delete) 4. 触发事件 (insert/update/delete) 1、创建一个名为tg1的触发器,当向t1表中插入数据前,就向a表中插入一条数据 delimiter // mysql中可以转换结束符 mysql>create trigger tg1 before insert on t1 for each row #固定写法 ->begin -> insert into a values (4); ->end//
19. 什么是组合索引,及使用情况?
将两个字段共同添加一条索引 例子:当前组合索引是这样一个顺序 ind_status_email(status,email) 单独查询status时,可以用到这个索引,单独查询email时,却用不到 再问: id name password 建立组合索引 怎么建立?为什么? name,password 因为先到先得, name查询是多!!! 很少会通过password来查 先到先得 如何设置我索引? 根据字段的辨识度来做
20. 为什么like在%第一个字符用不到索引?
like %校 会查处当前所有的姓, 再去查名中有没有校 所以 会进行全表扫描,浪费性能
21.测试分析sql语句
普通查询分析:
desc select * from users 或 explain select * from users 效果一样
关键字段: table:输出结果集的表名
key:表示实际使用的索引
keys_possible(可能用到的索引)
rows:扫描行的数量
22. 为什么不分开加索引?而非要加组合索引?
1. 索引不是越多越好. 浪费资源 索引暂用资源,影响插入性能 2. 根据要加索引的字段辨识度而来. 如果你给辨识度小的字段加索引 第一, 加了你不常用 第二,影响性能 3. 尤其是 name pasword 经典的组合索引例子
23.慢查询是什么?及其操作?
MySQL记录下查询超过指定时间的语句,我们将超过指定时间的SQL语句查询称为“慢查询”。1、查看是否开启慢查询mysql> show variables like "%slow%"; log_slow_queries | OFF2、查看慢查询时间线mysql> show variables like "%long%";| long_query_time | 10.000000 | //默认10秒3、开启慢查询记录功能vi /etc/my.cnf [mysqld] #将慢查询日志写在这个文件中 ---log_slow_queries=slow.log #超过多少秒的算是慢查询 ---long_query_time=1 #自定义,和理解可,试验用1秒方便查看日志。4、重启mysqlps -le | grep mysqldpkill mysqld或者/usr/local/mysql/bin/mysqladmin –uroot –p shutdown(推荐,安全关闭)/usr/local/mysql/bin/mysqld_safe --user=mysql &重启后慢查询功能开启5、查看慢查询次数mysql>show status like "Slow_queries"; //当前链接,超时的查询次数mysql>show global status like "Slow_queries"; //全局的 如果有慢查询,需要去日志中分析,到底是什么原因 vi /usr/local/mysql/data/slow.log #慢查询日志文件在开启慢查询功能后自动生成 需要将里面的SQL语句,用desc 分析,如果发现没有索引,则添加索引,如果是用不到索引,则修改SQL语句。6、查看MySQL的各项状态*(了解)show session status; 当前连接(可以省略session)show global status; 全局,服务器启动以来 筛选一部份内容查看: show status like "com_insert%"; 执行insert操作的次数,一次查询只累计加1 show status like "com_update%"; show status like "com_delete%"; show status like "com_select%"; show global status like "com_select%"; //不管有没有查到数据,都算一次查询操作 只针对于InnoDB存储引擎的: show global status like "innodb_rows%"; InnoDB_rows_read InnoDB_rows_updated InnoDB_rows_inserted InnoDB_rows_deleted
24.bin.log日志是什么?
记录数据库变化操作的二进制日志文件记录了所有的数据库变化操作(数据增删改,创建表等)在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复
25.聚簇索引和非聚簇索引的区别?
聚簇索引: 聚簇索引是顺序结构与数据存储物理结构一致的一种索引,并且一个表的聚簇索引只能有唯一的一条;说明: 平时习惯逛图书馆的童鞋可能比较清楚,如果你要去图书馆借一本书,最开始是去电脑里面查书名然后根据书名来定位藏书在那个区,哪个书柜,哪一行,第多少本。。。清晰明确,一目了然,因为藏书的结构与图书室的位置,书架的顺序,书本的摆放顺序与书籍的编号都是从大到小一致的顺序摆放的,所以很容易找到。比如,你的目标藏书在C区2柜3排5仓,那么你走到B区你就很快知道前面就快到了C区了,你直接奔着2柜区就能找到了。 这就是雷同于聚簇索引的功效了,聚簇索引,实际存储的循序结构与数据存储的物理机构是一致的,所以通常来说物理顺序结构只有一种,那么一个表的聚簇索引也只能有一个,通常默认都是主键,设置了主键,系统默认就为你加上了聚簇索引,当然有人说我不想拿主键作为聚簇索引,我需要用其他字段作为索引,当然这也是可以的,这就需要你在设置主键之前自己手动的先添加上唯一的聚簇索引,然后再设置主键,这样就木有问题啦。非聚簇索引: 非聚簇索引记录的物理顺序与逻辑顺序没有必然的联系,与数据的存储物理结构没有关系;一个表对应的 非聚簇索引可以有多条,根据不同列的约束可以建立不同要求的非聚簇索引;说明: 同样的,如果你去的不是图书馆,而是某城市的商业性质的图书城,那么你想找的书就摆放比较随意了,由于商业图书城空间比较紧正,藏书通常按照藏书上架的先后顺序来摆放的,所以如果查询到某书籍放在C区2柜3排5仓,但你可能要绕过F区,而不是A.B.C.D...连贯一致的,也可能同在C区的2柜,书柜上第一排是计算机类的书记,也可能最后一排就是医学类书籍;
26.mysql分区有哪几种?
RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
27.MyISAM和InnoDB的区别?从事物和表结构分析?
1.MyISAM不支持事务,InnoDB是事务类型的存储引擎,当我们的表需要用到事务支持的时候,那肯定是不能选择MyISAM了2、MyISAM只支持表级锁,,而InnoDB支持行级锁和表级锁默认为行级锁3、MyISAM引擎不支持外键,InnoDB支持外键4、MyISAM支持全文类型索引,而InnoDB不支持全文索引5、MyISAM引擎的表在大量高并发的读写下会经常出现表损坏的情况6、MyISAM保有表的总行数,InnoDB只能遍历
28.InnoDB共享表空间和独立表空间的优缺点?
优点: 共享表空间: 可以放表空间分成多个文件存放到各个磁盘上(表空间文件大小不受表大小的限制,如一个表可以 分布在不同步的文件上)。数据和文件放在一起方便管理 独立表空间: 1.每个表都有自已独立的表空间。 2.每个表的数据和索引都会存在自已的表空间中。 3.可以实现单表在不同的数据库中移动。 4.空间可以回收(除drop table操作处,表空不能自已回收) a) Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通 过:alter table TableName engine=innodb;回缩不用的空间。 b) 对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。 c) 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会 处理.缺点: 共享表空间: 所有的数据和索引存放到一个文件中意味着将有一个很常大的文件,虽然可以把一个大文件分成多 个小文件,但是多个表及索引在表空间中混合存储,这样对于一个表做了大量删除操作后表空间中 将会有大量的空隙,特别是对于统计分析,日值系统这类应用最不适合用共享表空间 独立表空间: 单表增加过大,如超过100个G 相比较之下,使用独占表空间的效率以及性能会更高一点
29.Node.js 是什么?
Node.js是一个让JavaScript运行在服务器端的开发平台.
30. Node.js的特点
单线程 | 非阻塞I/O | 事件驱动
1). 单线程
所有客户端请求的连接 都使用一个线程来处理.nodejs 不是为每个用户 创建一个新的连接,而是仅仅使用一个线程.单线程 带来的好处: 操作系统 不会为新线程 创建 || 销毁 内容空间,而暂用额外资源.
2). 非阻塞I/O
I/O操作不会阻塞程序的运行
3). 事件驱动
客户端 请求建立连接,提交数据等行为,就会触发 相应的事件.在Node中,在一个时刻,只能执行 一个事件回调函数,但是在执行 一个事件回调函数的中途,可以转而处理其他事件(比如,又有新用户连接了),然后返回继续执行原事件的回调函数,这种处理机制,称为“事件环”机制.
4). 三特点说明
单线程
是为了 减少内存的消耗,OS的内存(创建和销毁)但是,如果每个请求都有I/O,单线程就会 被 阻塞.
非阻塞I/O:
不会傻等着 I/O操作完成后,才去 执行后面的操作,而会 直接执行后的语句.非阻塞I/O,的操作,一个操作还未完成,下一个操作又来了.那么使用,事件环
事件驱动(事件环):
不管新用户的请求,还是老用户的请求(I/O操作),都将以事件的方式加入,事件环,等待调度.nodejs 所有的 I/O 都是异步的,回调函数套用回调函数.
31. Node.js 的优缺点?
1). 优点
善于 I/O,不善于计算.处理高并发服务器推送
2). 缺点
单一线程,一旦崩溃,整个服务就挂了.超人死了,世界都末日了.
32. Node.js适用场景
不能完全替代 传统的后端语言,但在某些方面优于传统. (nodejs 请求后端api)当应用程序需要处理大量并发的I/O操作,而在发出响应之前,应用程序内部 并不需要进行非常复杂的计算处理的时候,Node.js非常适合。Node.js也非常适合与web socket配合,开发长连接的实时交互应用程序。考试系统聊天室图文直播用户表单收集(大数据处理)复杂的计算提供 api(数据格式:json)
33 Node.js创建的http步骤
第一:引入http模块 var http = require('http'); // http 是内置模块 所以 不需要指定路径第二: 指定服务器 ip 和 端口号 var hostname = '127.0.0.1'; var port = '3000'; 第三 创建服务器 nodejs 所有的函数 都是 异步 回调函数 所以都需要用function 来接收 和处理 createServer 回调中有2个参数 req res 代表请求和响应var server = http.createServer(function(req,res){ 业务逻辑 res.end();});// 第四步 运行服务器server.listen(port,hostname,function(){});
34. Node.js中parse的用法
url.parse 会解析一个 URL 字符串并返回一个 URL 对象。url.parse(req.url,true) 加true会解析为JSON格式,不加解析为字串格式
35. Node.js文件怎么打开?
第一:引入模块 var fs =require('fs');第二: 语法 回调有两个参数 (err, data),其中 data 是文件的内容。 fs.readFile('./fei.jpg',function(err,data){ if (err) throw err; // 没有err 就 返回data // 设置mime 类型 res.writeHead(200,{"Content-type":"image/jpeg;charset=utf-8"}); 解析图片格式 res.writeHead(200,{"Content-type":"text/html;charset=utf-8"}); 解析文本 res.end(data); });
36.http 请求的流程?
1. 域名解析 2. 发起TCP的3次握手 3. 建立TCP连接后发起http请求 4. 服务器端响应http请求,浏览器得到html代码 5. 浏览器解析html代码,并请求html代码中的资源 6. 浏览器对页面进行渲染呈现给用户1、浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;2、解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;3、浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;4、服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;5、释放 TCP连接;6、浏览器将该 html 文本并显示内容;
37.node.js 中模块是什么?
在Node.js中,不可能用一个js文件去写全部的业务,肯定要有MVC. 它以模块为单位 划分所有功能,并且提供了一个 完整的模块加载机制,我们可以将应用程序 划分为各个不同的部 分. 每一个JavaScript文件都是一个模块;而多个JavaScript文件可以使用require引入,使他们共同实现了一个功能 模块.
38.node.js输出的方法?
输出变量/函数 Node.js中,JS文件中定义的变量、函数,都只在这个文件内部有效. 其他文件中需要引用变量、函数时,必须使用`exports对象`进行暴露(输出).使用者要用`require()`命令,引用执行这个JS文件. 输出一个类(构造函数) 可以用`module.exports = 构造函数名;`的方式 向外输出一个类
39. 谈谈对npm的理解?
这是一个工具名字.npm的主要职责是 安装开发包和管理依赖项. 安装开发包:安装 npm install命令;更新 npm update命令. 管理依赖项:借助package.json文件;最简单生成package.json的方法就是npm init开发时,会使用到各种功能的组件,所有组件都由我们自己来写代码的话,开发效率就会很低.我们不要重复的去造轮子,要学会使用已有的工具,来完善我们的项目,站在巨人的肩膀上去工作. npm是js世界里的一个伟大的社区,能够让开发者更加轻松的共享代码和共用代码片段或模块组件.
40. node.js中如何处理post请求?
““
相比较GET请求,POST请求比较复杂。因为Node.js认为,使用POST请求时,数据量会比较多。为了追求极致的效率,它将数据拆分成为了众多小的数据块(chunk),然后通过特定的事件,将这些小数据块有序传递给回调函数。
““
41. node.js中如何接收post数据?
特定的事件 去接收 addListener
querystring.parse 解析url 返回键值对的对象
特定的事件 去接收 addListener // 第一步: 设置空的标量 var postData = ''; // 第二步 开始监听 data req.addListener('data',function(chunk){ console.log(chunk); // 这里得到二进制数据 没有被解析 }); // 第三步: 监听结束 end req.addListener('end',function(){ // 处理得到的postData 是一个 拼接好的 url字符串 // 第四步: 处理接收完毕的数据 转化为对象 // 解析 url字符串 // querystring.parse 解析url 返回键值对的对象 var dataObj = querystring.parse(postData); });
42.学习框架的基础块?
1. 路由2. 中间件3. 数据操作4. 模板引擎
43. node.js如何处理图片上传?
一 引入模板 var formidable = require('formidable');二 // 接收参数 以及文件 var form = new formidable.IncomingForm(); // 设置上传,目录 form.uploadDir = "./uploads"; form.parse(req, function(err, fields, files) { // 处理 接受到的参数 再处理图片的上传 // 处理上传文件的名字 // 改名字的步骤 // 起名字 // 时间 + 随机数 + 后缀 var t = datetime.format(new Date(),'YYYYMMDDHHmmss'); var ran = parseInt(Math.random()*100000); var extname = path.extname(files.sexy_photo.name); // 执行改名字 旧名字 新名字 // 旧名字 // 当前目录 __dirname // path: 'uploads\\upload_621966da1b7a1d762c8a79c838f99b03', var oldpath = __dirname + '/' + files.sexy_photo.path; // 新名字 var newpath = __dirname + '/uploads/' + t + ran + extname; // 改名字 // rename fs.rename(oldpath,newpath,function(err){ res.end('图片上传成功'); });
44. ejs如何渲染模板?
Render(str,data,[option]):直接渲染字符串并生成htmlstr:需要解析的字符串模板data:数据option:配置选项
45.ejs常用标签?
<% %>流程控制标签<%= %>输出标签(原文输出HTML标签)<%- %>输出标签(HTML会被浏览器解析)<%# %>注释标签% 对标记进行转义-%>去掉没用的空格说明:ejs中的逻辑代码全部用JavaScript
46. 如何使用express创建一个服务器?
// 引入express 框架var express = require('express');// 创建一个http服务var app = express();// 定义一个路由app.get('/',function(req,res){ res.send('xxxx'); // 不建议使用end 因为end 会结束响应});// 运行服务// 可以不写第二个参数 代表本地 和外网 均可以访问app.listen(3000);
47.express如何定义路由?
app.get('/',function(req,res){ res.send('xxxx'); // 不建议使用end 因为end 会结束响应});app.post('/chenpin',function(req,res){ res.send('');});
48.res中 end和send的区别?
如果服务器端没有数据返回到客户端 那么就可以用 res.end但是 如果 服务器端有数据返回到客户端 这个时候必须用res.send ,不能用 res.end(会报错)
49. php命名空间是如何定义的?
命名空间通过关键字namespace 来声明。如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间,除了一个以外:declare关键字。命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误。这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀。基础命名空间将代码划分出不同的空间(区域),每个空间的常量、函数、类(为了偷懒,我下边都将它们称为元素)的名字互不影响, 这个有点类似我们常常提到的‘封装'的概念
50.php接口是如何实现的?
如果一个抽象类里面的所有方法都是抽象方法,且没有声明变量,而且接口里面所有的成员都是public权限的,那么这种特殊的抽象类就叫接口接口是什么? 使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。 接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。 接口中定义的所有方法都必须是公有,这是接口的特性。接口使用规范 接口不能实例化 接口的属性必须是常量 接口的方法必须是public【默认public】,且不能有函数体 类必须实现接口的所有方法 一个类可以同时实现多个接口,用逗号隔开 接口可以继承接口【用的少】