正是因为有你们的关注,才让我们的公众号关注人数超过了 500。 感谢所有人对我们公众号的关注,我们也尽量收集更好的资讯和工具来帮助到大家。 从计算机原理设计到代码实现。 从生活小感悟到签证旅行到你想去的地方。 我们尽量的多分享更多有趣的原创文章。 当然,如果您有更好的内容希望分享的话,也请随时注册登录我们的社区,分享你的见闻和真知灼见。 我们也会在那里恭候您的到来。 再次感谢所有朋友对我们的关注和厚爱。 https://www.isharkfly.com/t/topic/14875
正是因为有你们的关注,才让我们的公众号关注人数超过了 500。 感谢所有人对我们公众号的关注,我们也尽量收集更好的资讯和工具来帮助到大家。 从计算机原理设计到代码实现。 从生活小感悟到签证旅行到你想去的地方。 我们尽量的多分享更多有趣的原创文章。 当然,如果您有更好的内容希望分享的话,也请随时注册登录我们的社区,分享你的见闻和真知灼见。 我们也会在那里恭候您的到来。 再次感谢所有朋友对我们的关注和厚爱。 https://www.isharkfly.com/t/topic/14875
Java 是基于对象的,所以我们都需要以对象的想法来进行思维。 但 Java 又提供了 8 个基本类型,这 8 个基本类型基本上都和数字有关,是直接可以使用的类型。 基本类型 大小 包装器类型 boolean / Boolean char 16bit Character byte 8bit Byte short 16bit Short int 32bit Integer long 64bit Long float 32bit Float double 64bit Double void / Void String 不算基本类型,但是为了加快 String 的处理,Java 就顺手搞了一个 String Pool。 Java 基本类型 什么是基本类型? 直接可以计算的就是基本类型,基本类型不是对象。 所有的基本数据类型的大小(所占用的字节数)都已明确规定,在各种不同的平台上保持不变,这一特性有助于提高 Java 程序的可移植性。 基本类型就是已经定义好的,可以直接拿来计算和比较的那种。 包装类 既然我们有了基本类型,正如前面说的,Java 里面都是对象。 那么我们应该有必要创建一堆对象和前面说的 8 个基本类型进行对应。 这些对象就是针对基本类型创建的包装类( Wrapper Classes)。 为什么要有包装类 举个例子,我们指定 List 中需要存一堆 Integer 的对象。 如果我们定义的是基本类型,那我们怎么存到对象中呢? 我们是不是需要把基本类型转换为对象,然后再存进去,如果我们不提供包装类的话,就没有这个转换过程。 往大了说,基本数据类型没有办法使用 List 这个数据结构,这多无聊呀。 为了解决这个问题 Java 就搞了一个包装类,用来把基本数据类型转换为对象。 装箱和拆箱 既然东西有了,那么对这个转换的过程,自然就需要定义下概念了。 从基本数据类型类型转换为包装对象的过程就叫做装箱。 反过来就叫做拆箱了。 在老的 JDK ,这个过程都没有办法自动进行操作,每次要手动搞了一个类型转换。 其实这个过程每次都手动做的话,是非常繁琐的,所以在 JDK 进化后,现在全是自动化了,基本上都是自动类型转换了。 虽然有时候也会出点类型转换错误,但整体上提高了不少效率。 简单来说就是 JDK 在需要基本类型的时候,你定义却是对象,那么 JDK 自己帮你把这个拆箱过程给完成了,对你来说是透明的了。 缓存 既然有了装箱和拆箱的过程,如何提高这个效率,就是 JDK 需要考虑的东西了。 在这个过程中,缓存就被使用上了。 Integer valueOf(1); 就是用了缓存的典型例子。 JDK 的代码是这样的: @IntrinsicCandidate public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } 在这里,JDK 定义了一个最小值和最大值以便于加快类型转换的处理速度。 所以,下面的代码就有点意思了。 Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); System.out.println(i3==i4); 上面代码的结果是第一个判断为 TRUE,第二个为 False。 因为我们知道,对象使用 == 进行比较,比较的是内存地址,所以对值的比较我们通常会用 equals 来进行比较。 但是因为上面代码中的 Integer 小于 100,所以是从缓存中读的,这样会导致比较的时候返回 TRUE。 总结 在面试的时候,上面缓存中的内容是容易被喜欢扣细节的人问到的。 如果你真没有去看看 JDK 的文档,上面还真有点出问题。 但我们认为这个有点钻牛角尖的意思了,因为 Java 使用缓存的目的就是为加快程序的执行的。至于具体怎么实现,对大部分人来说这部分都是透明的。 通常实际编程的过程中,只需要了解自动拆装,并且如何定义变量,因为针对对象的定义和基本类型的定义是不一样的。 定义一个浮点对象,我们使用的代码是 Float x = 1F; ,在后面需要添加一个 F。 至于缓存部分,有时间就研究下,了解自动拆装是有缓存在里面,多是针对小范围 int 来使用的就可以了。 https://www.isharkfly.com/t/java/14873
AH-64“阿帕奇”直升机(英语:AH-64 Apache)是由美国波音公司为美国陆军所设计制造的一款主力武装直升机,得名于美洲原住民阿帕奇族。它是根据美国陆军的先进武装直升机(Advanced Attack Helicopter, AAH)项目所开发。 原本一架AH-64的单价是1,450万美元;不过希腊在2003年9月订购了12架的时候,包含武器和后勤支援,总额是6亿7,500万美元,单价也增加为5,625万美元。 航展中的直升机都没有挂载武器,仅有的就是展示了下挂载的弹药情况。 虽然驾驶舱是开放的,但是人很多,也没有办法让你上去直接进去动一动。 反而是 Sikorsky UH-60 Black Hawk 能够上去看看。 主要还是人蛮多的,找到一些比较好的角度也不太容易。 https://www.isharkfly.com/t/topic/14861
在去之前,并没有说有 B-52 参加,也算是个小意外了。 B-52“同温层堡垒”(英语:B-52 Stratofortress)是美国波音飞机公司研制的八引擎远程战略轰炸机,用于替换B-36和平缔造者轰炸机执行战略轰炸任务。1948年提出设计方案,1952年第一架原型机首飞,1955年批量生产型开始交付使用,先后发展了B-52A、B、C、D、E、F、G、H等8种型别,1962年停止生产,总共生产了744架飞机。 90年代是B-52轰炸机使用的鼎盛时期,有600多架B-52各型飞机在美国战略空军服役,以后大多数早期型号先后退役。 根据现场的提示,展示的这架飞机为 B52-H。 在飞机硕大的机翼下面,可以看到的 B52 的标志性引擎。 弹药挂载舱还是比较简洁,前后轮下面也能看到波音喜欢用的线控。 https://www.isharkfly.com/t/b-52/14862
这个题目其实不难,这是一个公司面试的时候要求的题目。 这个公司的面试有点意思,他们希望 Zoom 看我的电脑,然后让我解决问题。 题目 题目就非常简单了,他们给了我 2 个字符串。 其中一个是测试字符串,另外一个是元音字符,然后让把含有元音字符的单词输出。 给出的字符串分别为: String strTransform = "AI is driving the world crazy"; String Vowels = '"aeiou"; 思路 在面试的时候,有关字符串的处理非常常见。 通常需要考虑的的是大小写,空格,特殊字符等问题。在 Java 中,如果处理不好会容易空对象异常。 对于这个题目,可以使用子函数的方法,让逻辑更加清晰点。 可以首先在方法上面定义元音字母。 定义好子函数后,让这个子函数对输入的字符串进行判断。 为了便于数据遍历,在判断之前,可以简单的把给出的字符串放到 List 中。 这样你更好遍历,通常我们可以用 List.of 这个方法。 通常这里我们还有很多其他的方法可以用,Lists 这个方法是在 JDK 里面的,可以不依赖其他的 Package ,这样如果不让你用自己的 IDE 的时候,你更容易让在线的编译器通过。 运行结果。 运行的结果如下: 因为这个代码比较简单,而且我们只是测试下,所以我们就不放到代码库里面。 https://www.isharkfly.com/t/java/14841
这个问题在 Java 面试的时候大概率会被问到。 不是因为这个问题有什么复杂的,只是因为这个地方超出人类认知,你相信吗? 比较什么 如果你上培训班或者在学校学习的话,你的老师大概率可能会告诉你对于: 基本类型:比较的是值是否相同; 引用类型:比较的是引用是否相同; 本来这里就有点复杂了,还非要搞出另外 2 个概念。 比较好记的就是 == 比较的是内存地址,equals 比较的是具体的值。 对上面的问题,所谓的基本类型,因为没有对象话,所以 JVM 没有为基本类型创建实例化后的对象,因此 == 就可以直接用了,因为 2 个相同的基本类型的值的地址是一样的。 String 为什么不行 String 在 Java 里面有点奇葩,因为 String 是在是用得太多了。 所以 Java 为 String 搞了一个 String Pool,对于程序中,你这样定义的字符 String s1 = "iSharkFly";这个数据是存储在 String Pool 里面的。 因为 String 在 Java 里面被定义为不可变。等下一次你定义一个 s2 的时候,如果是同样的值, s1 和 s2 是相同的,因为都在 String Pool 里面。 String 还有另外一个初始化方法:` String s1 = new String(“iSharkFly”); 这个方法初始化的 String 是一个对象,这个对象没有放在 String Pool 里面,这个对象在 Heap 内存中。 所以: String s1 = new String("iSharkFly"); String s2 = new String("iSharkFly"); 的内存地址是不相同的,但是值相同。 使用 == 比较,上面就没有办法比较。 查看下面的代码: String s1 = new String("iSharkFly"); String s2 = new String("iSharkFly"); log.debug("hashCode - {}", s1.hashCode()); log.debug("hashCode- {}", s2.hashCode()); log.debug("identityHashCode- {}", System.identityHashCode(s1)); log.debug("identityHashCode - {}", System.identityHashCode(s2)); 程序输出: 我们会看到地址是不相同的。 hashCode 都知道 hashCode 会返回对象的 HashCode 来识别对象,为什么上面的地址是一样的? 因为 hashCode 会在程序中被重写。 下面的是 String 的 HashCode 代码。 JDK 已经对代码进行了重写。所以 hashCode 并不能完全标识内存地址。 所以,我们只能使用 System.identityHashCode 方法来获得内存地址。 总结 equals 和 == 在 Java 面试中经常会遇到。 只需要记住的是 == 比较的是内存地址,在对值进行比较的时候并不可靠。 在实际编码过程中,这种比较也比较常见的,所以还是有必要了解下这个。 https://www.isharkfly.com/t/java-equals/14839
如你对 Abstract 修饰的抽象类不是非常了解的话,请自行先考古下。 这篇文章需要对 Java 定义过的抽象类有一些基本的了解才可以。 抽象类和抽象方法 用 Abstract 修饰的类,叫做抽象类,那么用 Abstract 修饰的方法叫做抽象方法。 在 Java 中,喜欢用一些修饰关键字来对类或者变量或者方法来进行修饰。修饰的目的是更加明确一些类或者方法,或者变量的使用。 可以简单的理解为,使用关键字来修饰过的东西用来限制使用范围而已。 关于抽象类和抽象方法: 用 abstract 修饰过的方法所在的类一定是抽象类。 用 abstract 修饰过的类,不一定有抽象方法。 什么是接口 和 abstract 修饰过的类比起来,接口是用 interface 来修饰的,这个是在用 abstract 修饰的类上面进行进一步的限制和简化。 而接口中只能存在 public abstract 方法。 用很多人常使用的定义,接口就就是类似墙上的电源插头,上面定义了某个方法,然后让别人去实现的。 打个不是否恰当的比喻,为了从接口中获得电力,你管这个电力是火电还是核电。 正是因为这样的关系,所有接口中定义的方法必须要有实现。 一个类可以实现多个接口,但接口中定义的所有方法必须全部要实现。 接口中的变量会被隐式地指定为 public static final 变量(并且只能是 public static final变量,用 private 修饰会报编译错误),而方法会被隐式地指定为 public abstract 方法且只能是 public abstract 方法(用其他关键字,比如 private、protected、static、 final 等修饰会报编译错误)。 接口和抽象类的关系 首先可以理解为 interface 就是 abstract 的一个子集,内容和信息比 abstract 更加精简。 interface 中的方法是用来实现的,abstract 中的方法是用来继承的,这 2 个用途不一样。 因为 abstract 不能实例化,那么 interface 也肯定不能实例化了。 实际使用 举个实际使用的例子,我们现在有一个这样的需求,发送一个 HTTP 请求,获得用户的数据。 当我们希望对这个进行实现的时候,我们可以使用 apache 的 httpclient 这个包来完成 http 的调用,我们也可以使用 OKHttp 这个包来实现 http 的调用。 为了定义大家都使用的方法,我们就在这 2 个调用之前,定义了一个接口来要求我们的 2 个子类分别使用不同的包来实现完成调用返回结果。 小问题 如这里,我们只有一个实现,还有必要定义接口吗? 这个问题问得就非常好,如果你真只有一个实现的话,定义接口就纯粹属于脱了裤子放屁了。 当然你是可以定义的,只是定义的接口没有什么太大的意义,因为你就使用了这一个实现,何必再增加一个类搞得程序难读,直接使用实现类就好了。 总结 接口在 Java 中非常常用,但实际使用上,用不好会增加复杂性和没有必要的程序设计。 在日常开发中,大部分公司可能会选择用 Spring 框架。 单例 是Spring 当中bean 的默认范围(Scope)。Spring 容器会为某个bean 定义对象创建唯一的实例。 对于一般公司在初期可能更多的是关注业务实现,他们并不在意使用某种类实现,比如说上面的实现的 http 调用,可能就用了 OkHttp 实现就好了。 抽象出来各种接口,其实比较麻烦,软件开发的同事基本上就不写接口了。 这也导致了在你的软件项目中,看到接口的地方越来越少了。因为等于要多写一个类,同时还在这个类中写了不同的限制方法,如果我要加一个方法在接口中,所有的实现类都要加。 如果开始就设计不好的话,要加方法还挺繁琐。 在 IntelliJ IDEA 中,可以单击接口签名的 I 标记来看看有多少类实现了这个接口。 所以,有关接口的定义,目前更多用在很多八股文的面试题中,有些所谓的架构师会问下你接口是干什么的,很多情况下可能他们自己都已经不写接口了。 https://www.isharkfly.com/t/java-abstract-interface/14838
进入90年代,随着便利店商品销售在加油站经营中重要性的日渐突出,更加速了加油站管理自动化的进程。 如果早上出门比较早的话,在路上的加油站稍微大点的,通常都能够提供早餐。 当然也不要指望这个早餐有多么复杂和好吃,通常也就是快速热一下的热狗和三明治了。 说真的,好吃是真的谈不上,但是在必要的时候能够很快速的解决下肚子的问题。 在加油站的便利店内,咖啡和各种饮料也是必不可少的。 在加油的同时,北美这边也就比较习惯的随便在加油站带一杯咖啡就离开了。 在北美,加油站文化随处可见。 https://www.isharkfly.com/t/topic/14754
有个花坛也就算是边境了,可以说一个不太正经的边境吧。 当然也不会是想象中的那么容易就过去的了,通常在美加边境都有不少的 CBP 边境巡逻车。 对没有合理证件入境的,估计也不一定有什么好的脸色。 在边境边上找了好几年前来过的一家餐馆了解决下午饭的问题。 感觉上又发现了一个宝藏牛排。 通常牛排都是烤的多,这次却意外的有机会尝试了下用水烤的牛排,也感觉上是别有一番风味。 和朋友相约,下次再来。 https://www.isharkfly.com/t/topic/14753
短回答就是:不能 这里有 2 个概念,什么是抽象类和什么是实例化。 实例化 实例化简单来说就是为 Java 中使用的对象分配存储空间。 抽象类 从代码上来说,抽象类就是一个用 abstract 关键字来修饰的类。 这个类除了不能被实例化以外,其他都能做。 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。 // Java program to demonstrate abstract class // cannot have instance public abstract class ClassOne { public void printSomething() { System.out.println("Hello in abstract class"); } } class CreateClassOne { public static void main(String[] args) { // instance of abstract // class "ClassOne" ClassOne obj = new ClassOne(); } } 上面的代码运行时候将会出现错误: prog.java:17: error: ClassOne is abstract; cannot be instantiated ClassOne obj = new ClassOne(); ^ 1 error 因为你尝试实例化这个抽象类。 为什么不能实例化抽象类 很多人在这里都有点懵,为什么我就不能实例化抽象类。 正如我们上面说的,实例化就是为类分配需要的内容空间,以便于类去进行计算。 因为抽象类没有足够的信息, JVM 没有办法知道抽象类到底给他们分配什么。比如说没有具体的成员变量和成员方法。 你说,我们可以这样呀: HashMap hashMap = new HashMap(); AbstractMap abstractMap = new TreeMap(); 这样是对 abstractMap 进行实例化吗?这显然不是。 这是你用抽象类的名字定义了一个 Map,但是这个 Map 是用 TreeMap 实例化的。 最后你内存里面得到的是一个 TreeMap 而不是 abstractMap。 https://www.isharkfly.com/t/java/14751