您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

java基础 一些可能还未知道的Java小知识

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

因为是对象方法,不像静态方法那么好理解。在调用对象方法的时候需要是个实例对象。当调用sp.transform实际在调用String f() 有点像多态的性质,RTTI。该方法为对象方法。所以需要一个对象才能执行,所以传入X x。如果没有提示编译器异常。

在这里插入图片描述
纯粹的函数式语言在安全性方面更进一步。它强加了额外的约束,即所有数据必须是不可变的:设置一次,永不改变。将值传递给函数,该函数然后生成新值但从不修改自身外部的任何东西(包括其参数或该函数范围之外的元素)。当强制执行此操作时,你知道任何错误都不是由所谓的副作用引起的,因为该函数仅创建并返回结果,而不是其他任何错误。

个人认为: 这所谓的不安全 指得是当一个生命变量指向该创建函数得时候,没有得到一个确定的答案(return Effectively fina值,就是未改变过的值)。
因为是局部变量才会这样 。在创建时候不会因为函数调用结束而消失,还是存在在内存当中。所以有必要变成如此
在这里插入图片描述
流式编程有分为3个过程,创建流,中间操作,终端操作。要明白流是一种单向管道。想要弄明白一个流到底是在做什么,那就要看清楚上一个流操作返回了什么结果,让下一个流继续操作。要明白流操作是和lambda函数式编程要求一样,不对外造成影响。是开辟了一个新的数据在内部进行迭代操作

注意到上图中的1 调用steam方法时候,返回了一个生成随机数的流范围[100,1000]
注意到图2 问题点在于Pair::getI。因为我清楚记得Function函数接口 R apply(X x) 需要传入值,得到一个返回值。 然而getI 是一个无参方法。为什么可以放到Function里面。仔细看1中返回是一个Obj(也就是Pari) getI作为不是一个对象方法需要一个实例对象。所以Pair::getI内部传入一个对象调用getI

如下图
在这里插入图片描述
##异常
在这里插入图片描述
在这里插入图片描述

异常方法继承规则

abstract class Inning {
 Inning() throws BaseballException {}
}
public class StormyInning extends Inning {
public StormyInning()
            throws RainedOut, BaseballException {}
} 

子集继承基类。构造方法必须抛出基类构造方法的异常

abstract class Inning { 
    public void event() throws BaseballException {}
    public abstract void atBat() throws Strike, Foul;
    public void walk()  {} // Throws no checked exceptions
}
interface Storm {
    void event() throws RainedOut;
    void rainHard() throws RainedOut;
}
public class StormyInning extends Inning implements Storm { 
	    // Regular methods must conform to base class:
//    @Override
//    public void walk() throws PopFoul {
//        throw new PopFoul();
//    } //Compile error
// Interface CANNOT add exceptions to existing
// methods from the base class:
 @Override
 //public void event() throws RainedOut {}
// If the method doesn't already exist in the
// base class, the exception is OK:


    @Override
    public void rainHard() throws RainedOut {}
    // You can choose to not throw any exceptions,
// even if the base version does:
    @Override
    public void event()  {}
    // Overridden methods can throw inherited exceptions:
    @Override
    public void atBat() {}
}
} 

在子类实现抽象方法的时候,可以抛出任意异常,没有限制。也无需抛出抽象方法的异常。道理很简单。因为实现方式实在子类实现。没写怎么知道处理什么异常。

在子类实现具体方法的时候,父类没有抛出异常。子类只能抛出运行时异常。不能抛出非运行时异常。非运行时异常就是程序员必须处理的异常。父类没有抛出,子类也没办法抛出。因为是程序员必须处理的异常。所以站在多态的角度可以执行。但是站在编译期。为了安全确实不行。

在父类和接口有同样的方法时候。抛出不一样的异常情况下。很显然抽象方法不关我们的事。所以只负责关心父类的具体什么方法。

RTTI Runtime Type Imformati/identity

在这里插入图片描述
static final 修饰的变量会在类初始化之前就有值
光static 在之后

RTTI和反射的区别

RTTI:如果你不知道对象的确切类型,RTTI 会告诉你。但是,有一个限制:必须在编译时知道类型,才能使用 RTTI 检测它,并对信息做一些有用的事情。换句话说,编译器必须知道你使用的所有类。是一种多态上面的思想。在编译期间,编译器就会检查.class文件。检验
反射:.class文件编译期。无法检查其真实身份。由运行时打开并检查

RTTI和多态的区别

RTTI向下转型,多态是向上转型。

Generic

泛型作用:简单的概括就是把运行时异常,编程编译器异常。因为java中的泛型不像c++一样。java泛型为了兼容之前写下的代码。所以使用了具有擦拭功能的泛型。就是在运行期间。jvm是不知道你的具体类型的(List = (JVM)List, T = Object , T<? extend father> = father), 从反编译过后的源码来看
String a = (String) Object obj 和 String a = Object obj 是相等的 。他们都会在转移之前底层调用checkcast进行较量。 如果不正确就报 ClassCastException异常。

<? extend A> 和 < T extend A>的区别

T被叫做泛型,是一种用于定义变量,表示未知变量。 当泛型作用在public class上面。就是在初始化的该类的对象的时候声明。当泛型作用于方法的时候;public todo(T x){} 又入参决定返回的类型。他是一种认为在编译期真实存在,表未知。在运行时被擦拭的一种标志。
?被叫做通配符,用来表示边界bound,有时候可以跟T 用法一样。但是多用在声明变量中 如 List<? extend T> list = new ArrayList();

Thread

为什么 用Long[] 存取的结果 比用 long[] 存取的结果要慢很多。类比于其他基本数据类型和他的包装类

在这里插入图片描述
long[] 存储在内容中的数据是连续的,并且是值本质。通过cpu的预判。会缓存接下来的数据。
而Long[]尽管也是一个连续存储在内存当中,但是他存取的是指向long值得索引。而long值得索引是不连续得。不紧多了一层取值操作。还不能缓存long数据。所以导致差异如此之大。

steam和CompletableFuture在函数式编程当中都不用能::的方式调用一个有异常抛出的方法只能通过try。catch lamda表达式进行。

在这里插入图片描述

同步状态缺失

在这里插入图片描述
就算synchronized给evenInCrement方法上锁了。该方法也不是线程安全的
因为非静态方法绑定是同一个对象。就是new A()调用一个synchronized等待的时候,不能再调用其他的方法了。除非在方法内部调用。这也说明了为什么叫对象锁。不同的对象对于非静态方法可以同时调用。言归正传,因为getAsInt没有上锁。所以该方法无须等待evenIncrement,就能执行。所以这回造成了,尽管evenIncrement上了锁。但在执行i++;i++;途中。另一个线程可能回去寄存器取值。造成安全问题。解决方法给getAsInt上锁,或者i+=2

在这里插入图片描述

锁静态方法,锁的是类。类是全局唯一。所以懂得都懂,只要调用了一个上锁得方法,就会堵塞。但是看到上图很奇怪得一点。从执行调用来看。应该是121才对,可是为什么都是112。为什么会先执行第一个方法等待5秒,最后在执行2呢。我试过把2放在最前面。就会变成211.我猜测是jvm内部指令重排照成的。因为他已经加载了方法1的方法。所以内部认为在处理同样的方法执行就更快一些,所以就会早上上面的结果。会指令重排的原因是程序认为已最佳的方式执行,并且不会对结果造成影响。==写不出 ==为了验证下面这一点。我改一下代码。让它不出现执行重拍


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进