自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(50)
  • 收藏
  • 关注

原创 Kotlin新手教程九(协程)

async实际上启动了一个单独的协程,与launch类似,但是launch返回一个Job且无附带任何结果值,async返回一个Deferred(一个轻量级的非阻塞future),可以使用.await()在一个延期时间取得最终的值。注意,如果只是在 println 中调用了 await() 而不首先调用 start() ,这将形成顺序行为,因为 await() 会启动协程并等待其完成,这不是 lazy 模式的预期结果。} 内部的代码块提取到独立的函数中。如果我们忘记保持对新启动的协程的引用,它还会继续运行。

2023-02-22 18:09:12 1194 1

原创 Kotlin新手教程八(泛型)

然而, 内联函数的具体化的类型参数会由调用处内联函数体中的类型实参所代入,因此可以用于类型检测与转换, 与上述泛型类型的实例具有相同限制。运行时泛型类型的实例不保留关于其类型实参的任何信息。有些时候, 你可能想表示你并不知道类型参数的任何信息, 但是仍然希望能够安全地使用它. 这里所谓"安全地使用"是指, 对泛型类型定义一个类型投射, 要求这个泛型类型的所有的实体实例, 都是这个投射的子类型。in可以使类型参数逆变,只能用作输入,也就是可以作为入参的类型但是无法作为返回值的类型。(消费者使用)修饰符。

2023-02-21 15:38:24 716

原创 Kotlin新手教程七(委托)

委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。kotlin中使用by实现委托。

2023-02-21 14:30:02 495

原创 Kotlin新手教程六(数据类、密封类、枚举类、泛型)

在某种意义上,他们是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。有些时候, 你可能想表示你并不知道类型参数的任何信息, 但是仍然希望能够安全地使用它. 这里所谓"安全地使用"是指, 对泛型类型定义一个类型投射, 要求这个泛型类型的所有的实体实例, 都是这个投射的子类型。一个枚举类可以实现接口(但不能从类继承),可以为所有条目提供统一的接口成员实现,也可以在相应匿名类中为每个条目提供各自的实现。泛型一般可以用于类、接口、方法上。

2023-02-20 11:43:19 500

原创 Kotlin新手教程五(扩展)

这样的扩展可以在对象变量上调用, 即使其值为 null,并且可以在函数体内检测 this == null,这能让你在没有检测 null 的时候调用 Kotlin 中的toString():检测发生在扩展函数的内部。这就是因为扩展函数式静态分发的:调用的扩展函数是由函数调用所在的表达式的类型来决定的, 而不是由表达式运行时求值结果决定的。对于分发接收者与扩展接收者的成员名字冲突的情况,扩展接收者优先。扩展听起来很强大,但实际不是真正的修改他们所拓展的类,仅仅是可以通过使用该类型的变量用点表达式调用新函数。

2023-02-17 17:54:45 1289

原创 Kotlin新手教程四(抽象类和接口)

上例中D调用 super< A >.foo()和 super< B >.foo(),所以如果调用D的foo方法就会输出AB,我们也可以选择调用任意一个,这样其实是比Java更好的,因为在Java里面如果要实现多个接口,且里面有重复的方法名,那么其实覆盖不覆盖也无所谓,因为没有方法体。这一规则既适用于继承单个实现(bar())的方法也适用于继承多个实现(foo())的方法。通过 SAM 转换, Kotlin 可以将其签名与接口的单个抽象方法的签名匹配的任何 lambda 表达式转换为实现该接口的类的实例。

2023-02-17 14:44:32 529

原创 Kotlin新手教程三(类与继承)

在构造派生类的新实例的过程中,第一步完成其基类的初始化(在之前只有对基类构造函数参数的求值),因此发生在派生类的初始化逻辑运行之前。也就是说,当你实例化一个子类时,首先会初始化父类的主构造方法,父类的初始化代码块和初始化属性,接下来才是子类的。2.主构造器不能包含除属性声明的任何代码块,初始化的代码可以放到以init关键字作为前缀的初始代码块中。注:使用override修饰的方法实际效果也相当在重写的情况下使用open修饰了,如果不想再被其子类重写,那么可以使用final修饰。

2023-02-17 11:51:09 1402

原创 Kotlin新手教程二(Kotlin基本数据类型及基础语法)

Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作(但是可以显示把字符转换为数字),Char 必需是单引号 ’ 包含起来的。数组在 Kotlin 中使用 Array 类来表示,它定义了 get 与 set 函数(按照运算符重载约定这会转变为 [])以及 size 属性,以及一些其他有用的成员函数。这里虽然都是将num的值赋值给a和b,但是Int?

2023-02-16 17:33:20 704

原创 Kotlin新手教程一(Kotlin简介及环境搭建)

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,它也可以被编译成为 JavaScript 源代码(方便在没有JVM的设备上运行)。它主要是由俄罗斯圣彼得堡的 JetBrains 开发团队所发展出来的编程语言,其名称来自于圣彼得堡附近的科特林岛。

2023-02-16 15:21:25 2282

原创 Java虚拟机(JVM)

JVM是Java Virtual Machine的简称,翻译过来就是java虚拟机。虚拟机是指通过软件模拟具有完整硬件功能的、运行在一个完全隔离环境中的完整计算机系统。java能够那么火热,JVM功不可没。java的宣传口号是“一次编写,处处运行”,依靠的就是JVM,那么这个功能是怎么实现的呢?因为当你在IDE上写完代码编译后,JVM会为其生成一个.class文件,也叫字节码。当你把这个字节码放到另外一个系统上,只要都安装了JVM,那么这个java程序也能在另一个系统中运行。...

2022-08-11 23:25:28 925

原创 规避这些坑,能让你在查询数据库时更快

在数据库中,对于查询操作比较频繁的表,可以使用索引,索引又分为主键索引和非主键索引(有人也分为聚簇索引和非聚簇索引),我们先来看看主键索引是如何提高查询性能的。索引经历了几个阶段,第一个阶段使用的是二叉树,将数据直接存储在各个节点上,虽然相对一般查询来说也提高了效率,但是由于层级太高,查询和维护的时候都比较麻烦;第二阶段是B-数,此时也是将数据存储在各个节点上,虽然提高了维护效率,但是加载全部的信息还是需要不少的时间;第三阶段是B+数,该阶段将索引存储到B+树上,非叶子节点不存储数据,叶子节点也不存储数据,

2022-07-12 16:13:40 627

原创 带你快速学习Spring

Spring的官方解释很多,总的来说Spring就是包含了众多⼯具⽅法的 IoC 容器。工具方法很容易理解,这里不再赘述,容器的话只要你学过java,多多少少会接触一些容器,比如Map,List这类存放数据的容器;再比如Tomcat是Web容器,但是loC这个词貌似就很陌生了,接下来我们着重学习什么是loC。loC 是英文 Inversion of Control 的缩写,翻译过来就是控制反转 。所以Spring实质上就是一个“控制反转”的容器。接下来我们通过例子理解什么是控制反转。传统造车假设传统

2022-07-10 22:22:01 447

原创 MySQL中的删除:drop,delete,truncate的区别和联系

drop是DDL(数据定义语言),用于整张表的删除,删除的时候不仅删除了表中的数据,还删除了表结构。(也就是使用drop删除表后,数据库中便查询不到该表)语法:drop table 表名;注:drop命令后不可使用where等命令。delete是DML(数据操作语言),用于对表中数据的删除,不会删除表结构,也就是说即使你使用delete from 表名;将表中所有数据都删除了,该表依然存在。delete的删除原理:在InnoDB数据库引擎下,将要删除的数据添加一个删除标记,该表的实际大小不会产生变化

2022-06-02 07:59:18 14404

原创 你知道http协议各版本之间的区别吗?

HTTP 0.9是最初的HTTP协议,已经过时。特点:这一版本在请求和响应中加入了HTTP版本号,这一特点在之后的版本中保持不变。相对于HTTP 0.9 新增以下特性:这是目前最流行的HTTP协议,我在有时候做一些小网站的时候也会使用。相对于HTTP 1.0 新增以下特性:为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。但目前似乎还没流行起来。主要新增特性:HTTP3.0 在2018年发布,基于谷歌的QUIC,底层使用udp代码tcp协议。主要提升:

2022-06-01 08:43:02 2622

原创 数据库和表的基本操作

1.数据库操作创建数据库:create database [数据库名]切换(进入)数据库:create database [数据库名]删除数据库:drop database [数据库名]显示所有数据库:show databases;显示当前所在数据库:select databa();2.MySQL数据类型在学习表之前,需要先学习MySQL的基本数据类型,这样更方便我们去定义表,操作表。2.1数值类型数值类型有9个(有一个为BIT(M),常用Boolean对应BIT,默认为1),大家

2022-05-31 17:56:55 304

原创 CSS选择器常见用法

一、单选择器1.id选择器id选择器使用 HTML 元素的 id 属性选择元素id选择器只能选择唯一的特定的元素,因为它在HTML页面中时唯一的选择特定的id元素,可以使用#后面加元素id# col{ color:red;}2.类选择器类选择器使用HTML元素的class属性选择元素类选择器可以选择多个class属性值相同的元素选择某一类,可以使用.加上类名.col{ color:red;}将所有类名为col的元素颜色设置为红色3.标签选择器标签选择器使用HT

2022-05-30 22:59:09 1099

原创 MySQL的安装与配置

之前学习了MySQL,但是由于时间过于久远有些知识点有些模糊,借此机会写一个系列文章,主要目的是为了更加巩固自己的知识,当然也希望能够帮助到刚接触MySQL的小伙伴,大家一起努力,一起进步。文章目录一、安装MySQL二、MySQL的配置一、安装MySQL要学习MySQL,首先我们要先把软件安装好,才能进行下一步。下载MySQL(https://downloads.mysql.com/archives/community/)通过这个网址选择不同版本的MySQL,我们这里用MySQL5.7.27作为.

2022-05-30 21:44:27 511

原创 为什么说HashMap是线程不安全的?

一、头插法导致死循环在jdk1.7以前,HashMap在进行扩容时采用的是头插法,可能当时别人觉得这样比较高效,但是也带来了线程安全问题。刚开始时HashMap是这样的:正常扩容后是这样的:但如果是在多线程下,两个线程的指向3:此时线程1比线程2先执行,那么线程1就会指向7,将线程7.next指向了3,:但是对于线程2来说,3.next=7;所以就形成了死循环,也就是3和7构成了环。二、数据覆盖在jdk1.8以后,改了1.7以前的小毛病,但是新的问题又来了,我们来看下源码:

2022-04-25 10:10:28 5899 7

原创 常见锁策略和CAS你真的清楚了吗?

一、常见锁策略1.1乐观锁和悲观锁乐观锁:这种锁策略表示认为数据不会发生冲突,只有在数据更新时才会对冲突进行检测,如果没有发生冲突就可以直接更新数据,如果发生冲突就将数据返回给用户,让用户自己决定处理。(下文会讲解乐观锁的实现CAS)悲观锁:这种锁策略认为数据一定会发生冲突,所以在数据被访问的时候,就给数据加上锁,直到数据处理结束释放锁。(synchronized和Lock都是使用悲观锁策略)我们在认识锁策略的时候,不能只通过名称就辨别好坏,比如乐观锁和悲观锁,听起来悲观锁更逊色一些。但其实乐

2022-04-24 21:00:59 252

原创 java中wait()和sleep()的区别

一、wait和sleep的相同点都可以使线程休眠都可以响应interrupt的相应二、wait和sleep的区别wait和sleep在参数传递上大致相同,但传递值为0时,就是天壤之别,看下面的代码:public class Demo8 { public static void main(String[] args) { Thread thread1=new Thread(()->{ System.out.println("线程一开始启动")

2022-04-20 15:42:43 828 2

原创 Java中死锁产生的原因及解决方法

一、什么是死锁死锁就是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的现象,若无外力作用,他们都无法推进下去。简单来说就是A和B若同时都有一个资源,在此之外还想拥有对方的资源,由于资源如果在某个人手里,其他人就无法获得,所以变成了你不让我,我不让你,就僵持下了。下面我们来看下具体代码:public class CreateDeadThread { public static void main(String[] args) throws InterruptedExce

2022-04-20 09:00:52 8594

原创 synchronized的底层实现和运行原理

synchronized同步锁是通过JVM的监视器实现的,而监视器又是依赖操作系统的mutex实现的。监视器监视器就是一个概念或者机制,用来保障在任何时候,只有一个线程能够执行指定代码。synchronized的底层实现就是依赖JVM的监视器实现的执行流程HotSpot 虚拟机中,Monitor 底层是由 C++实现的,它的实现对象是 ObjectMonitor,ObjectMonitor 结构体的实现如下:ObjectMonitor::ObjectMonitor() { _head

2022-04-19 11:35:55 1471

原创 什么是线程安全问题,出现了你会解决吗?

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

2022-04-18 22:53:47 503

原创 七大排序,你都搞懂了几个

一、冒泡排序1.1 冒泡排序一般写法冒泡排序就是将相邻的两个数字比较,如果顺序错误就将两个数交换,每轮遍历后右侧位置为最大值。 public void bubbleSort(int[] arr){ for (int i = 0; i <arr.length ; i++) { //每轮遍历后,第arr.length-i-1之后的元素都有序了,不用比较 //减少程序运行次数 for (int j = 0; j < a

2022-04-16 10:46:23 382

原创 线程的状态

一、线程的状态线程一般有7个状态,但jdk中只规定了6种状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED、),因为它把READY状态归为了RUNNABLE,我们可以通过以下代码查看线程的状态public class Test { public static void main(String[] args) { Thread.State[] arr=Thread.State.values(); for

2022-03-30 10:00:00 282

原创 你真的会用Thread类嘛?

一、线程创建线程的创建总的来说有7种方式,我把这几种方式分为以下三大类,其中有带返回值的(继承Thread类创建线程;实现Runnable接口创建线程),也有不带返回值的(实现Callable接口创建线程)。1.1继承Thread类创建线程1.继承Thread类创建线程这种方法创建线程显得太过复杂,一般不推荐public class ExtendThread { public static void main(String[] args) { CreadThread thr

2022-03-28 22:56:06 2109

原创 进程与线程的区别和联系

一、进程进程(Process)是操作系统分配资源的基本单位,⼀个进程拥有的资源有⾃⼰的堆、栈、虚存空间(⻚表)、⽂件描述符等信息。 从编程的⻆度来理解进程,可以把它看作是⼀个类或⼀个 PCB(Process Control Block)进程控制块的结构体。1.1进程的本质进程本质就是⼀个 PCB(Process Control Block)结构体,类似于 Java 中的类。进程中包括了以下几个属性:PID:进程的唯一身份标识(当重启进程后PID会更改)进程状态:新建状态、就绪状态、运行

2022-03-27 18:45:55 1546

原创 【java】String类详解?看这篇就够了

一、创建字符串直接赋值String str="hello";创建String对象赋值 String str = new String("hello");使用字符数组,再将字符数组转化为字符串 char[] arr={'h','e','l','l','o'}; String str=new String(arr);二、字符串比较相等如果我们比较两个整形变量是否相等,直接用==比较就可以,但若要比较两个字符串呢? String str="hello";

2021-11-22 11:30:15 728

原创 抽象方法与接口的区别

一、抽象类与抽象方法使用abstract修饰的类叫做抽象类使用abstract修饰的方法叫做抽象方法,抽象方法只允许声明,不允许实现(无方法体)抽象方法或者抽象类不能使用final修饰,因为final修饰类表示不能被继承,而抽象类的作用大多都需要子类继承而设计;使用final修饰方法表示子类不可重写,那该抽象类将会毫无意义。同样,也不可以使用static修饰方法,既抽象方法必须是实例方法抽象类中可以有抽象方法,也可以有普通方法抽象类不能使用new创建对象若一个类继承了抽象类,那么该类必

2021-11-21 19:45:26 224

原创 【java】面向对象三大特性(封装、继承、多态)

一、封装封装是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。在java中我们一般使用private对类中属性或方法进行封装。使用封装能够更好的保护代码,防止有的代码被其他类的代码随意访问,加强了代码的安全性;而且适当的封装能使代码更容易理解和维护。我们可以这样实现封装:class Packging{ private String secret="secret"; public String addressable="addressable"; private

2021-11-14 15:37:06 92

原创 【java】方法重载和方法重写

一、方法重载方法重载指在同一个类中,两个或多个方法名称相同,参数类型或参数个数不同。那么为什么会有这个东西呢,举个栗子,你定义一个add方法,计算两个整数之和,那如果要计算两个浮点数之和,这时就需要重写写一个方法,那就叫它addDouble,那如果计算float类型的呢?叫他addFloat。如果要定义一个方法计算三个int类型的数之和,则需要定义一个方法叫addIntThreeNumber,这样让使用者对于调用方法时很麻烦,本来很简单的一个功能,还需要记住那么多方法名。我们的想法是,调用者只需要使用

2021-11-12 17:02:49 668

原创 【java数据结构】单链表(不带虚拟头结点)

一、单链表的创建单链表是一个物理不连续,逻辑连续的线性表。那么我们要实现单链表,就需要定义一个类Node,这个类中存储Node结点的数据及下一个结点的引用。创建Node类,类中有整形属性data存储Node的值;next存储Node下一个结点的引用。创建Node类的两个构造方法,一个只有一个参数data,表示只知道值,不知道该节点的下一个引用是啥;一个有参数data和next,表示既知道该节点的值,又知道下一节点的引用。创建SingleList类,创建属性size用于记录链表的长度,head用于

2021-11-08 17:09:46 529

原创 【java数据结构】顺序表

文章目录一、顺序表的创建二、顺序表添加元素2.1 头部插入元素(头插法)2.2顺序表尾部插入元素(尾插法)2.3在顺序表index位置插入元素三、顺序表查找3.1按值查找3.2按索引查找四、顺序表的删除4.1按索引删除4.2按值删除4.2.1删除首次出现的元素4.2.2删除所有值为data的元素五、顺序表的修改5.1按索引号修改5.2按值修改六、顺序表的优缺点分析6.1优点6.2 缺点七、顺序表源码顺序表一般使用数组实现,数组不仅逻辑连续,其物理也连续,下面我们将实现顺序表的基本操作(增删查改)一、

2021-11-06 14:59:56 1180

原创 【java基础】构造方法、构造代码块、静态代码块

一、 构造方法构造方法为java中常见的方法,一般使用new关键字实例化新对象时会被调用,用于完成初始化操作new执行过程一般分为两步:1.为对象分配内存空间。2.调用对象的构造方法。在写构造方法时要注意以下三点:方法名称必须与类名称相同构造方法中没有返回值类型声明每一个类中一定至少存在一个构造方法若在编写时没有定义构造方法,则编译器自动生成一个无参构造比如:class Person { private String name;//实例成员变量 private int age;

2021-10-24 16:24:05 1428

原创 汉诺塔(Hanoi Tower)

问题分析汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?递归的思想就是把难题简单化,假设三根柱子我们分别命名为A、B、C,我们的想法就是把A上的圆盘转移到C柱上。假设A盘只有一个圆盘,

2021-10-18 11:00:06 497

原创 【java基础】(一)数据类型与运算符

文章目录一、变量与类型1.1整形变量(int)1.2长整形变量(long)1.3双精度浮点型变量(double)1.4单精度浮点型变量(float)1.5 字符类型变量(char)1.6字节类型变量(byte)1.7短整型变量(short)1.8布尔类型变量(Boolean)1.9变量的命名规则1.10类型转换二、运算符2.1算术运算符2.2逻辑运算符2.3位运算符2.4条件运算符一、变量与类型变量指的是程序运行时可变的量. 相当于开辟一块内存空间来保存一些数据.类型则是对变量的种类进行了划分, 不

2021-10-12 14:47:23 77

原创 【C语言】关于结构体你一定要知道的事

文章目录????一、结构体???? 1.1结构体类型的声明???? 1.2结构体的自引用???? 1.3结构体变量的定义???? 1.4 结构体变量的初始化????1.4.1定义时初始化????1.4.2 定义后逐个赋值????1.4.3定义时乱序赋值????1.4.4定义时乱序赋值(c++风格)????1.5 结构体内存对齐????1.5.1结构体对齐规则????1.5.2为什么存在结构体对齐????1.5.3 修改默认对齐数????1.5.4计算结构体大小练习题????一、结构体???? 1.1结构

2021-09-21 12:15:00 155

原创 字符函数和字符串函数模拟实现(strlen,strcpy,strcat,strcmp,strstr,memcpy,memmove)

文章目录????‍????求字符串长度????‍♂️strlen模拟实现????‍♂️strlen非递归实现????‍♂️strlen递归实现????‍????长度不受限制的字符串函数????‍♂️strcpy模拟实现????‍♂️srtcat模拟实现????‍♂️srtcpy模拟实现????‍????长度受限制的字符串函数????‍♂️strncpy模拟实现????‍????字符串查找????‍♂️strstr????‍????内存操作函数????‍♂️memcpy????‍♂️memmove模拟实现

2021-09-19 18:47:54 215

原创 C语言strstr函数改进(解决自己给自己追加)

目录# strstr的模拟实现# 的# strstr的模拟实现 # strstr分析 这个函数不能实现自己给自己追加的原因在于;两个指针同时操作一个字符串,当*dest找到 '\0' 之后,*src开始追加,当追加完一个字符后,*src往后走一位,*dest指向的 '\0'被覆盖,*dest就必须往后走一位,找到下一个'\0',找到之后*src又开始追加,不断重复,导致程序崩溃。# strstr模拟实现 函...

2021-09-19 15:09:32 350

原创 深度剖析数据在内存中的存储(原码、补码、反码、大小端、面试题)

我们知道基本的数据类型有char ,short, int, long,long long ,float,double.那么这些数据在内存中是怎样存储的呢? 一、整形在内存中的存储int a=10;这句代码大家应该扫一眼就能看懂;这代表我们为变量a分配4个字节;那这个数据在内存中怎么存储的?我先为大家解开谜题:对于整形来说,数据存放内存中其实是存放补码。补码又是什么鬼?接下来咱们先补补课计算机中的有符号数有三种表示方法,既原码、反码、补码三种表示方法均有符号位和数值位两...

2021-07-26 16:22:02 588 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除