原标题:面试官:背了几道面试题就敢说熟悉Java源码?我们不招连源码都不会看的人|原力计划
作者|Baldwin_KeepMind
责编|伍杏玲
出品|CSDN博客
我的真实经历
标题是我2019.6.28在深圳某500强公司面试时候面试官跟我说的话,即使是现在想起来,也是觉得无尽的羞愧,因为自己的愚钝、懒惰和自大,我到深圳的第一场面试便栽了大跟头。
我确信我这一生不会忘记那个燥热的上午,在头一天我收到了K公司的面试通知,这是我来深圳的第一个面试邀约。收到信息后,我激动得好像已经收到了K公司的Offer,我上网专门查了下K公司的面经,发现很多人都说他们很注重源码阅读能力,几乎每次都会问到一些关于源码的经典问题,因此我去网上找了几篇关于String、HashMap等的文章,了解到了很多关于Java源码的内容。看完后我非常的自信,心想着明天的所有问题我肯定都可以回答上来,心满意足的睡觉。
面试的那天上午,我9点钟到了K公司楼下,然后就是打电话联系人带我上去,在等待室等待面试,大概9:30的时候,前台小姐姐叫到了我的名字,我跟着她一起进入到了一个小房间,里面做了两个人,看样子都是做技术的(因为都有点秃),一开始都很顺利,然后问道了一个问题“你简历上说你熟悉Java源码,那我问你个问题,String类可以被继承么”,当然是不可以继承的,文章上都写了,String是用final修饰的,是无法被继承的,然后我又说了一些面试题上的内容,面试官接着又问了一个问题:
“请你简单说一下substring的实现过程”
是的,我没有看过这一题,平时使用的时候,也不会去看这个方法的源码,我支支吾吾的回答不上来,我能感觉到我的脸红到发烫。他好像看出了我的窘迫,于是接着说“你真的看过源码么?substring是一个很简单的方法,如果你真的看过,不可能不知道”,到这个地步, 我也只好坦白,我没有看过源码,是的我其实连简单的substring怎么实现的都不知道,我甚至都找不到String类的源码。
面试官说了标题上的那句话,然后我面试失败了。
我要感谢这次失败的经历,让我打开了新世界,我开始尝试去看源码,从jdk源码到Spring,再到SpringBoot源码,看得越多我越敬佩那些写出这优秀框架的大佬,他们的思路、代码逻辑、设计模式,是那么的优秀与恰当。不仅如此,我也开始逐渐尝试自己去写一些框架,第一个练手框架是“手写简版Spring框架--YzSpring”,花了我一周时间,每天夜里下班之后都要在家敲上一两个小时,写完YzSpring之后,我感觉我才真正了解Spring,之前看网上的资料时总觉得是隔靴搔痒,只有真正去自己手写一遍才能明白Spring的工作原理。
再后来,我手上的“IPayment”项目的合作伙伴一直抱怨我们接口反馈速度慢,我着手优化代码,将一些数据缓存到Redis中,速度果然是快了起来,但是每添加一个缓存数据都要两三行代码来进行配套,缓存数据少倒无所谓,但是随着越来越多的数据需要写入缓存,代码变得无比臃肿。有天我看到@Autowired的注入功能,我忽然想到,为什么我不能自己写一个实用框架来将这些需要缓存的数据用注解标注,然后用框架处理呢?说干就干,连续加班一周,我完成了“基于Redis的快速数据缓存组件”,引入项目之后,需要缓存的数据只需要用@BFastCache修饰即可,可选的操作还有:对数据进行操作、选择数据源、更新数据源、设置/修改Key等,大大提高了工作效率。第一次自写轮子,而且效果这么好,得到了老大哥的肯定,真的很开心。
那么现在我要问你三个问题:
你看源码么?
你会看源码么?
你从源码中有收获么?
看源码可以获得什么
1.快速查错、减少出错
在编码时,我们一般都发现不了RuntimeException,就比如String的substring方法,可能有时候我们传入的endIndex大于字符串的长度,这样运行时就会有个错误:
Stringindexoutofrange: 100
有时候稀里糊涂把代码改正确了,但是却不知道为什么发生这个异常,下次编写的时候又发生同样的问题。如果我们看过源码,我们就可以知道这个异常发生的原因:
publicString substring( intbeginIndex, intendIndex ) {
if(beginIndex < 0) { //起始坐标小于0
thrownewStringIndexOutOfBoundsException(beginIndex);
}
if(endIndex > value.length) { //结束坐标大于字符串长度
thrownewStringIndexOutOfBoundsException(endIndex);
}
intsubLen = endIndex - beginIndex;
if(subLen < 0) { //起始坐标大于结束坐标
thrownewStringIndexOutOfBoundsException(subLen);
}
return((beginIndex == 0) && (endIndex == value.length)) ? this
: newString( value, beginIndex, subLen);
}
源码中给出了三个可能抛出上面异常的情景,那我们就可以根据这三种情景去检查我们的代码,也以后在编码的时候注意这些问题。
2.学习编程习惯
还是说上面的substring源码,请注意他的return,如果是你,你会怎么写?如果没有看过源码,我肯定会写成下面:
if((beginIndex == 0) && (endIndex == value.length)) returnthis;
returnnewString( value, beginIndex, subLen);
虽然功能是一样的,但是运用三元运算可以用一行代码解决问题,而且又不用写if语句,现在我已迷上了三元运算符,真的很好用。
3.学习设计模式(针对新手)
好吧!我摊牌了, 作为一个半路出家的程序员,我没有接受过系统化的教学,所有的都是自学,在之前我完全不了解设计模式,只知道有23种设计模式,最多知道单例模式。
不了解设计模式最主要的原因是当时没有实战经验,自己写的项目都是比赛项目,完全不用不上设计模式,基本上是能跑就行。我第一次接触设计模式是在log4j的工厂模式,当时是完全不懂工厂模式该怎么用,就是看着log4j的源码一步步学会了,然后自己做项目的时候就会有意无意的开始运用设计模式,下面是我项目中使用单例模式获取配置类的代码:
import java.util.ResourceBundle;
publicclassConfigration{
privatestaticObject lock= newObject;
privatestaticConfigration config = null;
privatestaticResourceBundle rb = null;
privateConfigration( String filename) {
rb = ResourceBundle.getBundle(filename);
}
publicstaticConfigration getInstance( String filename) {
synchronized( lock) {
if( null== config) {
config = newConfigration(filename);
}
}
return(config);
}
publicString getValue( String key) {
String ret = "";
if(rb.containsKey(key))
{
ret = rb.getString(key);
}
returnret;
}
}
3.小总结
你们可能很多人都会觉得上面的东西很简单,请不要被我误导,因为上面都是最简单的例子,源码中值得学习的地方非常多,只有你自己去看,才能明白。
阅读源码的正确姿势
我们这里以一个热度非常高的类HashMap来举例,同时我非常建议你使用IDEA来阅读编码,其自带反编译器,可以让我们快速方便的看到源码,还有众多快捷键操作,让我们的操作爽到飞起。
1.定位源码
其实定位的时候也有多种情况:
Ctrl+左键
像这种情况,我们要进入只属于HashMap类的方法,我们可以直接Ctrl+左键就可以定位到源码位置了。
Ctrl+Alt+B
HashMap的put方法是重写了Map的方法,如果我们用Ctrl+左键,会直接跳到Map接口的put方法上,这不是我们想要的结果,此时我们应该把鼠标光标放到put上,然后按下Ctrl+Alt+B,然后就出现了很多重写过put方法的类。
找到我们需要查看的类,左键点击就可以定位到put方法了。
2.查看继承关系
一个类的继承关系很重要,特别是继承的抽象类,因为抽象类中的方法在子类中是可以使用的。
上一步中我们已经定位到了HashMap源码上,现在拉到最上面,我们可以看到类定义的时候是有一下继承关系:
publicclassHashMap< K, V> extendsAbstractMap< K, V>
implementsMap< K, V>, Cloneable, Serializable
当然,如果想更直观更详细的话,在IDEA中有个提供展示继承关系的功能,可以把鼠标放在要查看的类上,然后Ctrl+Alt+Shift+U,或者右键=》Diagrams=》Show Diagram,然后我们就可以看到继承关系:
然后大致查看下AbstractMap抽象类,因为有可能等下会用到。
3.查看类常量
我们进到HashMap构造函数时,发现了以下代码:
publicHashMap( intinitialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
我们只知道initialCapacity是我们传入的初始容量,但完全不知道这个DEFAULT_LOAD_FACTOR是什么、等于多少,我们可以先大致看一下这个类所拥有的的常量,留个印象就好,有利于等下阅读源码,Ctrl+左键定位到这个量的位置,然后发现还有好几个常量,常量上面有注释,我们看一下,这有助于我们理解这些常量:
这样,我们就对HashMap中常量的作用和意义有所理解了
4.查看构造函数
我们一般看一个类,首先得看这个类是如何构建的,也就是构造方法的实现:
/**
* 构造一个空的,带有初始值和初始加载因子的HashMap
* @paraminitialCapacity the initial capacity.
* @throwsIllegalArgumentException if the initial capacity is negative.
*/
publicHashMap( intinitialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
很明显,上面的构造函数指向了另一个构造函数,那么我们点进去看看
/**
*
* @paraminitialCapacity the initial capacity
* @paramloadFactor the load factor
* @throwsIllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
publicHashMap( intinitialCapacity, floatloadFactor) {
if(initialCapacity < 0)
thrownewIllegalArgumentException( "Illegal initial capacity: "+
initialCapacity);
if(initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if(loadFactor <= 0|| Float.isNaN(loadFactor))
thrownewIllegalArgumentException( "Illegal load factor: "+
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
这里就是我们构造函数实现的地方了,我们来一行一行的去分析:
1.我们的initialCapacity参数是我们一开始传进来的16,loadFactor是上一步中用的默认参数0.75f。
2.判断初始容量是否小于0,小于0就抛出异常,不小于0进行下一步。
3.判断初始容量是否大于最大容量(1 << 30),如果大于,就取最大容量。
4.判断加载因子是否小于等于0,或者是否为数字,抛出异常或下一步。
5.初始化这个HashMap的加载因子。
6.最后一行是HashMap的扩容机制,根据我们给的容量大小来确定实际的容量,我们来看一下该方法的源码。
staticfinal int tableSizeFor(int cap) {
intn = cap - 1;
n|= n >>> 1;
n|= n >>> 2;
n|= n >>> 4;
n|= n >>> 8;
n|= n >>> 16;
return(n < 0) ? 1: (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
这一步其实就是为了求大于我们设定的容量的最小2的幂数,以这个值作为真正的初始容量,而不是我们设定的值,这是为了随后的位运算的。现在我们解释一下上面的运算:
以cap=13为例,那么n初始=12,n的二进制数为00001100,随后一次右移一位并进行一次与n的或运算,以第一次为例,首先|=右边运算为无符号右移1位,那么右边的值为00000110,与n进行或运算值为00001110,反复运算到最后一步的时候,n=00001111,然后在return的时候便返回了n+1,也就是16.
至此,我们完成了一个空HashMap的初始化,现在这个HashMap已经可以操作了。
5.查看方法逻辑
我们一般使用HashMap的时候,put方法用的比较多,而且他涉及的内容也比较多,现在来定位到HashMap的put方法。
publicV put( K key, V value) {
returnputVal(hash(key), key, value, false, true);
}
put方法又调用了putVal方法,并且将参数分解了,key和value没什么好说的,我们来先看一下hash(key)这个方法干了什么。
staticfinalinthash(Object key){
inth;
return(key == null) ? 0: (h = key.hashCode) ^ (h >>> 16);
}
如果当前key是null,那么直接返回哈希值0,如果不是null,那就获取当前key的hash值赋值给h,并且返回一个当前key哈希值的高16位与低16位的按位异或值,这样让高位与低位都参与运算的方法可以大大减少哈希冲突的概率。
OK!多出来的三个参数,其中hash值的内容我们已经知道了,但是三个值都不知道有什么用,不要急,我们进入putVal方法。
/**
* Implements Map.put and related methods.
*
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal( inthash, K key, V value, boolean onlyIfAbsent,
boolean evict ) {
Node<K,V>[] tab; Node<K,V> p; intn, i;
if((tab = table) == null|| (n = tab.length) == 0)
n = (tab = resize).length;
if((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else{
Node<K,V> e; K k;
if(p.hash == hash &&
((k = p.key) == key || (key != null&& key. equals(k))))
e = p;
elseif(p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal( this, tab, hash, key, value);
else{
for( intbinCount = 0; ; ++binCount) {
if((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if(binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if(e.hash == hash &&
((k = e.key) == key || (key != null&& key. equals(k))))
break;
p = e;
}
}
if(e != null) { // existing mapping for key
V oldValue = e. value;
if(!onlyIfAbsent || oldValue == null)
e. value= value;
afterNodeAccess(e);
returnoldValue;
}
}
++modCount;
if(++size > threshold)
resize;
afterNodeInsertion(evict);
returnnull;
}
看这上面一堆代码,是不是又开始头疼了,不要怕他,我们一行一行分解他,就会变得很容易了。
第一步还是要看注释,注释已经翻译好了,请享用。
/**
* 继承于 Map.put.
*
* @param hash key的hash值
* @param keykey
* @param value 要输入的值
* @param onlyIfAbsent 如果是 true, 不改变存在的值
* @param evict iffalse, the table isincreation mode.
* @ return返回当前值, 当前值不存在返回null
*/
然后来看内容
1.创建了几个变量,其中Node是HashMap的底层数据结构,其大致属性如下:
staticclassNode< K, V> implementsMap. Entry< K, V> {
finalinthash;
finalK key;
V value;
Node<K,V> next;
Node( inthash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}
2.判断当前table是否为空,或者table的长度是否为0,同时给tab和n赋值,如果条件成立(当前的HashMap是空的),那就进行resize,并将resize的值赋予tab,把tab数组的长度赋予n,由于篇幅原因,这里不详细解说resize方法,这个方法内容比较多,在其他文章中也说了很多,今天的重点是说明如何去读源码,而不是HashMap。
3.判断底层数组中当前key值元素的hash值对应的位置有没有元素,如果没有,直接将当前元素放进去即可。
4.接上一步,如果底层数组对应位置中已经有值,那就进行其他的一些列操作把数据写入,并返回oldValue。
我们走完整个流程后,总结几个需要注意的点,比如HashMap.put方法里要注意的就是resize,尾插,树与列表之间的转换。
由于篇幅问题,这个方法里的内容,我只是简略的说一下,具体的查看源码的方式和之前大同小异,一步步分析即可。
6.小总结
查看源码的几个技巧:
1.Ctrl+左键或Ctrl+Alt+B定位到正确的源码位置
2.查看类里面一些量,有个大概的认识
3.查看构造函数看实例的初始化状况
4.如果代码比较复杂,分解代码,步步为营
5.其他的源码的阅读都可以按照这个套路来分析
作者=萌新,如有错误,欢迎指出。
阅读源码绝对是每个程序员都需要的技能,即使刚开始很难读懂,也要慢慢去习惯。
如果喜欢,欢迎点赞、评论、收藏、关注。
版权声明:本文为CSDN博主「Baldwin_KeepMind」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shouchenchuan5253/article/details/105196154游戏网
相关下载 |
原标题:海贼王中最像海贼的人,也是有故事的男人,他是黑胡子 黑胡子可以说是我们众多人讨厌又不怎么讨厌的人,说讨厌他将艾斯以及自己的“老爹”白胡子详情>>
原标题:为什么5G已经商用,5G手机也越来越便宜,使用5G的人还是不多呢? 时至今日,5G已经开始在许多城市大面积铺开商用,各家运营商的5G基站也是在慢慢进行详情>>
1、读书的时候,我的作文那叫一个烂!但我想到一个办法,就是中间先抄上各种小说内容,然后补上开头和结尾。办法绝对是好办法,作文成绩也明显见效。。。只是因为后来换详情>>
原标题:送给4月1日过生日的人一首生日歌,祝您生日快乐! 游戏网 详情>>
这西瓜真好,好想吃,就是现在有点贵! 我真担心你,你的狗拉不住怎么办?掉下去可就麻烦了! 孩子,你是这个操作的指挥者吗?还可以这样玩! 你别看,我真的是在工作!你详情>>
原标题:龙珠:再尝败绩,可爱的人造人!恐怖的实力 贝吉塔是真没赢过几次啊,而且赢的还都是小喽啰。 那美克星时候的那场宇宙大战中,贝吉塔就尝尽了败北的详情>>
女人在什么情况下,安慰不了?这样的问题,相信很多男人都能够回答上来,哪怕不去读芥川龙之介的语录,也能回答出一些来。毕竟现实中很多男人都惹过女人,都经历过安慰不详情>>
我一直都不认识路,到六年级才知道正确的方向是上北下南左西右东,到了中学快上完才能找出正确的方向(只限熟悉的地方)。 一次从一个第一次去的同学家出来,骑车回家,详情>>
原标题:现在用二次元做手机壁纸的人,你认为有多少是真的喜欢二次元 想必许多喜爱二次元的小伙伴们经常会把手机壁纸设置成自己喜欢的动漫角色吧,每当详情>>
给你花钱的人不一定爱你,不给你花钱的人一定不爱你。 我每次谈女朋友,相处几个月以后,我就会把我所有的银行卡交给女朋友,我的理由是,一是让她感觉到我对她是真心的详情>>
1.真事,我哥们半夜在别人窗前蹭wifi,女主人起来上厕所发现有人怀疑图谋不轨,便偷偷报了警!待警察来时了一把抓住我哥们,问你在干嘛呢?哥们神回复,草,没看见在看西游记详情>>
1.老板说出来你不信,今天早上排长队买了一个煎饼果子,刚挤出人群,一辆出租车在我身边缓缓经过,一妹子从副驾驶伸出手,抢走了我的煎饼果子,并扔给我五块钱:“哥!我赶时详情>>
原标题:杨超越闻“臭袜子”被吐槽,尬黑她的人有多无聊?? 请问你可以星标/置顶我吗 因为我不想在茫茫人海中失去你 昨天君君看到最好笑的事是 当红小花详情>>
<div class="intro"> <i></i> <p>“我习惯想好了就去做。”</p> <span></span> </div> <div class="endText" id="endText"> <p><!--StartFragment--><b style="color: rgb(151, 72, 6);">本文系网易沸点工作室《谈心社》栏目(公众号:txs163)出品,每天更新。</b><!--EndFragment--></p><p>知乎上有个问题:有哪些详情>>
原标题:海贼王中为路飞赌上一切的人!5位以命作赌,他赌上尾田的未来 海贼王是一部非常惜命的动漫,一旦角色死亡便少有复生的可能(布鲁克是例外)。所以,路详情>>
......................................................................................... 众所周知 传统的剪纸是这样的 红红火火 引人注目 .......详情>>
原标题:海外网友热议IG不敌JDG:给IG做BP的人应该被解雇!实在太烂了 4月9日晚上结束的LPL春季赛JDG和IG的比赛,最终JDG以2-0的战绩干脆利落地击败了IG,详情>>
原标题:知名女星直播曝圈内八卦!合作过的人都不放过?承诺大曝视帝猛料 特殊时期,因为公开参加活动的机会减少了,很多明星将更多的精力放在电商平台上,开详情>>
原标题:健身不分年龄!30岁以上的人,更应该坚持健身! 原创内容,擅自搬运者必究! 健身的文化席卷国内外,越来越多的人开始参与健身训练。 但也有很多人在详情>>
腐烂国度2主宰版养丧尸的人任务怎么做?想来很多朋友都还不是很清楚吧,所以呢小编今天给大家带来的就是腐烂国度2主宰版养丧尸的人任务攻略介绍,需要的朋友不妨进来看看。详情>>
原标题:男女相处时,对的人,会给你这几种感觉 对的人,一般是指相爱的情况,如果有一方属于爱意偏移或者模糊,都不能算是对的人。 真正对的人,不仅合适,而且详情>>
原标题:海贼王:鱼人的他,拥有着一颗侠心,甚平到底是个怎样的人? 海贼王的世界中有许多人物,个个都鲜活无比的形象,即使是反派也有是拥着善良的一面,可以说详情>>
任天堂Switch主机在全世界都陷入了库存短缺的窘境,某宝和某东上的零售价格(非国行)已经飙升至3500左右,被玩家们戏称为“理财产品”。任天堂也向日本用户发出官方通告,由于疫情详情>>
组图自水印,侵删 爱情这杯酒,谁喝都得醉!由此可见,我喝了八斤白酒会死=我谈恋爱会死,这就是我单身的理由没错了!赶快转发分享右下角,感受一下恋爱的真相吧! 详情>>
1 大家好,我是林兮。 知乎上有人问:真正爱你的男人是什么样? 有一个回答说:真正爱你的男人,绝对不会轻易对你说,等我。 何况连等都不说,屁都不放一个。 有个女生详情>>
关于考试的四种人设 这一刻,你妈妈就知道了你太多东西 当代网友的控楼能力 员工:想笑,不敢 来,各位开始你的表演! 今天,这个详情>>
1 大家好,我是林兮。 胡杏儿结婚时说过: “我的前前任和前任都很棒。他们一个教我做成熟优雅的女人,一个教我做独立懂事的大人。但我更喜欢现任,他教我做回小孩详情>>
原标题:巨蟹座的恋爱:小心翼翼的去暗恋一个人,遇到喜欢的人不敢表白 巨蟹座的喜欢:在试探的边缘进行 巨蟹座对于的喜欢是一直都在试探的边缘来进行详情>>
原标题:为什么坚持健身的人,会跟同龄人拉开差距? 原创内容,擅自搬运者必究! 当健身的文化开始席卷国内,追求健身的人也越来越多。 健身,是一个健康的词汇详情>>
原标题:歌手吴琦新歌上线 向光明《出发》向《最可爱的人》致敬 4月3日,歌手吴琦先后发行由苏武作词、吴琦作曲演唱、张帅编曲的公益单曲《出发》,由详情>>
原标题:致敬,新时代最可爱的人 图为6日,来自北京医院、北京大学第一医院等单位的557名支援湖北医疗队队员圆满完成任务后返回北详情>>
欢迎关注“创事记”的微信订阅号:sinachuangshiji 文/Will 来源:山河路人(ID:shanheluren) 01 2006年冬天的北京,位于故宫乾清详情>>
原标题:淘宝直播内容运营负责人简柔:将持续构造新的人货场 大家好,我是来自淘宝直播的简柔。今年以来,中国零售业的金额增速在放慢,同时整个互联网人口详情>>
我是小强,我不喜欢走,我喜欢跑。跑很远很久的那种。你是不是想到了《阿甘正传》,哈哈,差不多吧。反正在学校里没人能跑得过我。 你知道跑步的那种感觉吗?风从耳边详情>>
原标题:有钱就是硬气!Epic发动“钞能力”,悬赏百万寻找抹黑自家APP的人! 自从小学毕业以后,手谈姬就没有像现在这样长达两三月的时间呆在家里了。 有一详情>>
原标题:“跑着去见你想见的人吧!”全程高甜...酸了 长时间的封闭隔离 让有些人通过网恋收获了爱情 然鹅 另一些人 却被迫开启了异地恋的寂寞… 没详情>>
原标题:演员牛莉近照曝光,素颜出镜气质依旧,状态超好不像快50岁的人 4月6日一大早,演员牛莉在个人社交平台晒出了一段搞怪短视频。视频中的牛莉在软件详情>>
原标题:捷克总统:拿中国防疫物资质量做文章的人应该道歉 据央视新闻客户端消息,当地时间4月5日,捷克总统泽曼在接受当地媒体采访时表示,疫情在全世界蔓详情>>
原标题:双鱼座会借着酒劲向喜欢的人表白吗? 双鱼座真的很喜欢一个人的时候,就会变得很胆怯,因为他们害怕自己没有能力去和对方相匹配,总觉得自己根本就详情>>
Hi,我是提起裤子讲笑话的布斯基。 今天跟大家唠一唠人的梦想。记得这两年有一句话是“世界那么大,我想去走走”!引起了一大波网友的热潮。谁不想出去走走呢,关键详情>>