深入学习java源码,深入学习java源码之Math.scalb()与 Math.powerOfTwoF()

深入学习java源码之Math.scalb()与 Math.powerOfTwoF()

final关键字

final在Java中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误

凡是对成员变量或者本地变量(在方法中的或者代码块中的变量称为本地变量)声明为final的都叫作final变量。final变量经常和static关键字一起使用,作为常量。

final也可以声明方法。方法前面加上final关键字,代表这个方法不可以被子类的方法重写。如果你认为一个方法的功能已经足够完整了,子类中不需要改变的话,你可以声明此方法为final。final方法比非final方法要快,因为在编译的时候已经静态绑定了,不需要在运行时再动态绑定。

使用final来修饰的类叫作final类。final类通常功能是完整的,它们不能被继承。Java中有许多类是final的,譬如String, Interger以及其他包装类。

final关键字的好处

final关键字提高了性能。JVM和Java应用都会缓存final变量。

final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。

使用final关键字,JVM会对方法、变量及类进行优化。

创建不可变类要使用final关键字。不可变类是指它的对象一旦被创建了就不能被更改了。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销等等。

java中的assert(断言)

在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语句都 将忽略!),如果要开启断言检查,则需要用开关-enableassertions或-ea来开启。

assert关键字语法很简单,有两种用法:

1、assert

如果为true,则程序继续执行。

如果为false,则程序抛出AssertionError,并终止执行。

2、assert :

如果为true,则程序继续执行。

如果为false,则程序抛出java.lang.AssertionError,并输入。

1、assert关键字需要在运行时候显式开启才能生效,否则你的断言就没有任何意义。而现在主流的Java IDE工具默认都没有开启-ea断言检查功能。这就意味着你如果使用IDE工具编码,调试运行时候会有一定的麻烦。并且,对于Java Web应用,程序代码都是部署在容器里面,你没法直接去控制程序的运行,如果一定要开启-ea的开关,则需要更改Web容器的运行配置参数。这对程序的移 植和部署都带来很大的不便。

2、用assert代替if是陷阱之二。assert的判断和if语句差不多,但两者的作用有着本质的区别:assert关键字本意上是为测试 调试程序时使用的,但如果不小心用assert来控制了程序的业务流程,那在测试调试结束后去掉assert关键字就意味着修改了程序的正常的逻辑。

3、assert断言失败将面临程序的退出。这在一个生产环境下的应用是绝不能容忍的。一般都是通过异常处理来解决程序中潜在的错误。但是使用断言就很危险,一旦失败系统就挂了。

assert既然是为了调试测试程序用,不在正式生产环境下用,那应该考虑更好的测试JUint来代替其做用,JUint相对assert关键的所提供的功能是有过之而无不及。当然完全可以通过IDE debug来进行调试测试。在此看来,assert的前途一片昏暗。

因此,应当避免在Java中使用assert关键字,除非哪一天Java默认支持开启-ea的开关,这时候可以考虑。对比一下,assert能给你带来多少好处,多少麻烦,这是我们选择是否使用的的原则。

Modifier and Type

Method and Description

static double

scalb(double d, int scaleFactor)

返回 d 2 scaleFactor四舍五入,好像由单个正确四舍五入的浮点乘以双重值集合的成员执行。

static float

scalb(float f, int scaleFactor)

返回 f 2 scaleFactor四舍五入,就像一个正确圆形的浮点数乘以浮点值集合的成员一样。

java源码

public final class Math {

private Math() {}

public static double scalb(double d, int scaleFactor) {

// magnitude of a power of two so large that scaling a finite

// nonzero value by it would be guaranteed to over or

// underflow; due to rounding, scaling down takes takes an

// additional power of two which is reflected here

final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT +

DoubleConsts.SIGNIFICAND_WIDTH + 1;

int exp_adjust = 0;

int scale_increment = 0;

double exp_delta = Double.NaN;

// Make sure scaling factor is in a reasonable range

if(scaleFactor < 0) {

scaleFactor = Math.max(scaleFactor, -MAX_SCALE);

scale_increment = -512;

exp_delta = twoToTheDoubleScaleDown;

}

else {

scaleFactor = Math.min(scaleFactor, MAX_SCALE);

scale_increment = 512;

exp_delta = twoToTheDoubleScaleUp;

}

// Calculate (scaleFactor % +/-512), 512 = 2^9, using

// technique from "Hacker's Delight" section 10-2.

int t = (scaleFactor >> 9-1) >>> 32 - 9;

exp_adjust = ((scaleFactor + t) & (512 -1)) - t;

d *= powerOfTwoD(exp_adjust);

scaleFactor -= exp_adjust;

while(scaleFactor != 0) {

d *= exp_delta;

scaleFactor -= scale_increment;

}

return d;

}

public static float scalb(float f, int scaleFactor) {

// magnitude of a power of two so large that scaling a finite

// nonzero value by it would be guaranteed to over or

// underflow; due to rounding, scaling down takes takes an

// additional power of two which is reflected here

final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT +

FloatConsts.SIGNIFICAND_WIDTH + 1;

// Make sure scaling factor is in a reasonable range

scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE);

/*

* Since + MAX_SCALE for float fits well within the double

* exponent range and + float -> double conversion is exact

* the multiplication below will be exact. Therefore, the

* rounding that occurs when the double product is cast to

* float will be the correctly rounded float result. Since

* all operations other than the final multiply will be exact,

* it is not necessary to declare this method strictfp.

*/

return (float)((double)f*powerOfTwoD(scaleFactor));

}

// Constants used in scalb

static double twoToTheDoubleScaleUp = powerOfTwoD(512);

static double twoToTheDoubleScaleDown = powerOfTwoD(-512);

static double powerOfTwoD(int n) {

assert(n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT);

return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) <<

(DoubleConsts.SIGNIFICAND_WIDTH-1))

& DoubleConsts.EXP_BIT_MASK);

}

static float powerOfTwoF(int n) {

assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT);

return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) <<

(FloatConsts.SIGNIFICAND_WIDTH-1))

& FloatConsts.EXP_BIT_MASK);

}

}

public final class StrictMath {

private StrictMath() {}

public static double scalb(double d, int scaleFactor) {

return Math.scalb(d, scaleFactor);

}

public static float scalb(float f, int scaleFactor) {

return Math.scalb(f, scaleFactor);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值