资讯专栏INFORMATION COLUMN

ssssss

itvincent / 996人阅读

摘要:运算符主要介绍不常用到的位运算符,位运算符都是相对整型二进制数位来说的假设是一个被移位的整型数据,是位移量。按位运算符也可以操作逻辑型数据。所以,如果以后有人问你是值传递还是引用传递,你直接告诉他这是个无聊的问题。

Java基础 关键字

主要介绍不常用到的关键字:

native - native通常用来修饰方法,一个native方法就是一个Java调用非Java代码的接口(A native method is a Java method whose implementation is provided by non-java code.),也就是说该方法的实现由非Java语言提供。另外,调用native方法的其他类甚至不知道它所调用的是一个本地方法,JVM将控制调用本地方法的所有细节,即JNI框架,这里就不展开叙述了。

default - 定义注解时用于返回属性的默认值。Java 8用default来绕开已发布的接口无法再修改的障碍。在Java 8中,接口中的方法可以被实现。接口中被实现的方法叫做default方法,用关键字default作为修饰符来标识。当一个类实现一个接口的时候,它可以实现已经在接口中被实现过的方法,但这不是必须的。这个类会继承default方法。这就是为什么当接口发生改变的时候,实现类不需要做改动的原因。

volatile - 被其修饰的域在每次被线程访问时,都强迫从主内存中重读该成员变量的值;而且当成员变量发生变化时,强迫线程将变化值回写到主内存。这样在任何时刻,两个不同的线程总是看到域的同一个值,也称作线程可见性

Java语言规范中指出:为了获得最佳速度,允许**线程保存共享成员变量的私有拷贝**,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。这样当多个线程同时读写某个对象,并且没有进行同步时(不在同步代码快内),就需要让线程及时的得到共享成员变量的变化。而volatile关键字就是告诉JVM对于这个域不能保存它的私有拷贝,而应直接与其它线程共享。

由此可以,使用volatile屏蔽掉了JVM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

transient - 被其修饰的域不会被序列化,请查看序列化。

strictfp - 修饰符的一种,可应用于类、接口或方法。使用 strictfp 关键字声明一个方法或类时,该方法或类中所有的float和double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。通常处理器都各自实现浮点运算,各自专业浮点处理器为实现最高速,计算结果会和IEEE标准有细小差别。比如intel主流芯片的浮点运算,内部是80bit高精运算,只输出64bit的结果。IEEE只要求64bit精度的计算,你更精确反而导致结果不一样。所以设立严格浮点计算,保证在各平台间结果一致,IEEE标准优先,性能其次;而非严格的浮点计算是性能优先,标准其次。

const - Java保留字,不支持使用。

goto - Java保留字,不支持使用。

基本数据类型
Data Type Length(bit) Default Value (for fields)
boolean 1 false
byte 8 (byte)0
short 2-byte (short)0
char 2-byte "u0000"
int 4-byte 0
long 8-byte 0L
float 4-byte 0.0f
double 8-byte 0.0d

这8个基本数据类型可以分为两大类,一类是整型,另一类是浮点型。浮点型包括float和double类型,剩下的可以归为整型。整型是精确的,而浮点型是不精确的。如果要求数值的绝对精确,不要用浮点型,更多细节请查看精密计算。

除了上述8个基本数据类型, Java还通过类类型提供了对char串的支持。

Data Type Default Value (for fields)
String (or any object) null

这里还涉及到字符编码(比如ASCII和Unicode编码)等知识,请另行查阅。

另外,Java还提供了与基本数据类型相关的类,即包装类。尤其需要提到的是char的包装类Character,而不是String。为什么需要包装类这种东西?因为,基本类型不是对象,下面的代码在Java里不被允许:

7.toString();

也正是这一点,有人说Java不是完全面向对象的语言,而比如Ruby,其基本类型也是对象。所以在需要对象的地方,就需要与基本类型对应的包装类实例。

进制

Java支持二进制、八进制、十进制和十六机制的数值表示:

二进制:数字前加0b前缀,如0b101。

八进制:数字前加0前缀,如0107。

十进制:数字前不加前缀,如109。

十六机制:数字前加0x前缀,如0x10F。

运算符

主要介绍不常用到的位运算符,位运算符都是相对整型二进制数位来说的:

<< 假设a是一个被移位的整型数据,n是位移量。a<运算的结果是通过将a的所有位都左移n位,每左移一位,左边的高阶位上的0或1被移出丢弃,并用0填充右边的低位。更多细节请另行查阅。

>> 假设a是一个被移位的整型数据,n是位移量。a>>n运算的结果是通过将a的所有位都右移n位,每右移一位,右边的低阶位上的0或1被移出丢弃,并用0或1填充左边的高位。a是正数时用0填充,是负数时用1填充。更多细节请另行查阅。

>>> 假设a是一个被移位的整型数据,n是位移量。a>>>n运算的结果是通过将a的所有位都右移n位,每右移一位,右边的低阶位上的0或1被移出丢弃,并用0填充左边的高位。更多细节请另行查阅。

&(&=) 按位与。

|(|=) 按位或。

^(^=) 按位异或,相同为0,不同为1。

按位运算符也可以操作逻辑型数据。按位运算的一个典型应用是定义一组常量,将2的不同倍数赋予每个常量:

// Bit field enumeration constants - OBSOLETE!
public class Text {
    public static final int STYLE_BOLD = 1 << 0; // 1
    public static final int STYLE_ITALIC = 1 << 1; // 2
    public static final int STYLE_UNDERLINE = 1 << 2; // 4
    public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
    
    // Parameter is bitwise OR of zero or more STYLE_ constants
    public void applyStyles(int styles) {
        if ((styles & STYLE_BOLD) == STYLE_BOLD) {
            System.out.println("bold");
        }
        if ((styles & STYLE_ITALIC) == STYLE_ITALIC) {
            System.out.println("italic");
        }
        if ((styles & STYLE_UNDERLINE) == STYLE_UNDERLINE) {
            System.out.println("underline");
        }
        if ((styles & STYLE_STRIKETHROUGH) == STYLE_STRIKETHROUGH) {
            System.out.println("strikethrough");
        }
    }
}

这种表示法允许你用按位或|运算符将几个常量合并到一个表达式中,称作位域(bit field)

text.applyStyles(STYLE_BOLD | STYLE_ITALIC);

位域表示法也允许利用位运算符,执行联合、差集以及交集等操作。

访问权限
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
package-private(default) Y Y N N
private Y N N N

注意:Override可以减弱访问权限,但不能增强。

递归

#Todo#

标签

Java允许通过标签(结合关键字breakcontinue)实现流程控制,但最好不这样做:

outer: while (...) {
    inner: for (...) {
        if (...) {
            break inner;
        }
        continue outer;
    }
}
接口

语言层面上,相较于类,接口有着自己的一些特性。

接口的所有成员变量都是public static final的,无论你显式声明与否。为什么是这样,引用SO上的两个答案感受一下:

Protected methods are intended for sharing implementation with subclasses. Interfaces have nothing to offer as far as implementation sharing goes, because they have no implementation at all. Therefore all methods on interfaces must be public.
Because an interface is supposed to mean "what you can see from outside the class". It would not make sense to add non-public methods.

但是这里有个问题,因为Java 8支持接口提供默认的方法实现,这样的话,如果一个接口是为了被其它接口继承而设计的,受保护(protected)的方法是不是就有意义了呢?当然,这也是一种非常极端的用法,可能并不提倡。

接口的所有方法都是public abstract的,无论你显式声明与否;但Java 8 提供了接口方法的默认实现,叫做default方法,用关键字default作为修饰符来标识,这一定意义上破坏了这一约束。

接口本身是public abstract的,abstract修饰符被默认隐藏。

静态

静态代码的真正意义是什么?静态代码是属于类的代码,即便对象不存在,属于类的代码也存在也可访问,只要类已经被加载。#Todo#

值传递还是引用传递

Java是值传递还是引用传递?不知道这个问题有没有使你感到困扰,但这个问题确实一直困扰着我,我觉得对象是引用传递,但是很多教科书式的答案都是说Java只有值传递,直到我读到《Thinking in Java 4th Edition》里面的一段话,才豁然开朗:

This brings up the terminology issue, which always seems good for an argument. The term is "pass by value," and the meaning depends on how you perceive the operation of the program. The general meaning is that you get a local copy of whatever you’re passing, but the real question is how you think about what you’re passing. When it comes to the meaning of "pass by value," there are two fairly distinct camps:

Java passes everything by value. When you’re passing primitives into a method, you get a distinct copy of the primitive. When you’re passing a handle into a method, you get a copy of the handle. Ergo, everything is pass by value. Of course, the assumption is that you’re always thinking (and caring) that handles are being passed, but it seems like the Java design has gone a long way toward allowing you to ignore (most of the time) that you’re working with a handle. That is, it seems to allow you to think of the handle as "the object," since it implicitly dereferences it whenever you make a method call.

Java passes primitives by value (no argument there), but objects are passed by reference. This is the world view that the handle is an alias for the object, so you don’t think about passing handles, but instead say "I"m passing the object." Since you don’t get a local copy of the object when you pass it into a method, objects are clearly not passed by value. There appears to be some support for this view within Sun, since one of the "reserved but not implemented" keywords is byvalue. (There’s no knowing, however, whether that keyword will ever see the light of day.)

Having given both camps a good airing and after saying "It depends on how you think of a handle," I will attempt to sidestep the issue for the rest of the book. In the end, it isn"t that important – what is important is that you understand that passing a handle allows the caller’s object to be changed unexpectedly.

其实,对于Java这种纯面向对象的语言,无所谓值传递还是引用传递,更准确的理解就是传递的就是那个对象,所以对传递进来的对象的修改,会反映到原来对象上,这就足够了。只有在低级语言如C++才会需要明显区分地址、引用和值这些概念,而对于高级的面向对象语言则完全是多此一举。所以,如果以后有人问你Java是值传递还是引用传递,你直接告诉他这是个无聊的问题。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65560.html

相关文章

  • JS基础篇--replace替换全部的正确应用

    摘要:一般使用使用正则循环替换如下这种情况,表情标签的替换,我们需要正常的字符串替换,例如结合实现。 一般使用 var str = test-test-test; str = test-test-test.replace(test, ok); console.log(str); 使用正则: var str = test-test-test; str = test-test-test.repl...

    jackzou 评论0 收藏0
  • JS设计模式之Obeserver(观察者)模式、Publish/Subscribe(发布/订阅)模式

    摘要:观察者模式定义设计模式中对的定义一个对象称为维持一系列依赖于它观察者的对象,将有关状态的任何变更自动通知给它们。如图模式比较观察者模式则多了一个类似于话题调度中心的流程,发布者和订阅者解耦。 Obeserver(观察者)模式 定义 《js设计模式》中对Observer的定义:一个对象(称为subject)维持一系列依赖于它(观察者)的对象,将有关状态的任何变更自动通知给它们。 《设计模...

    荆兆峰 评论0 收藏0
  • SpringCloud(第 054 篇)简单 Quartz-Cluster 微服务,采用注解配置 Q

    摘要:加载配置文件失败加载配置文件失败添加定时调度任务定时调度任务添加定时调度任务定时调度任务执行的张表入数据库添加启动类简单微服务,采用注解配置分布式集群。 SpringCloud(第 054 篇)简单 Quartz-Cluster 微服务,采用注解配置 Quartz 分布式集群 - 一、大致介绍 1、因网友提到有没有采用注解式配置的Quartz例子,因此本人就贴上了这样一个样例; 2、至...

    isLishude 评论0 收藏0
  • 《Python有什么好学的》之修饰器

    摘要:然后煎鱼加了一个后再调用函数,得到的输出结果和加修饰器的一样,换言之等效于因此,我们对于,可以理解是,它通过闭包的方式把新函数的引用赋值给了原来函数的引用。 Python有什么好学的这句话可不是反问句,而是问句哦。 主要是煎鱼觉得太多的人觉得Python的语法较为简单,写出来的代码只要符合逻辑,不需要太多的学习即可,即可从一门其他语言跳来用Python写(当然这样是好事,谁都希望入门简...

    lewinlee 评论0 收藏0

发表评论

0条评论

itvincent

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<