首页 文章 精选 留言 我的

精选列表

搜索[微服务与微计算],共10000篇文章
优秀的个人博客,低调大师

Kotlin伴生对象与静态成员

一、解释 每个类可以对应一个伴生对象 伴生对象的成员全局独一份 伴生对象的成员类似于Java的静态成员 二、Java中 调用kotlin类的方法需要加上 @JvmStatic 调用kotlin类的成员变量需要加上 @JvmField 三、形如java.lang包中math类 它所有的方法全部都是静态的,在使用的时候,直接就可以math.xxx(方法) 四、形如Integer类中的方法,在Java中这样使用 Integer a = Integer.valueOf(3); 五、在Kotlin中,形如这样的可以直接调用 看一下代码 Integer a = Integer.valueOf(3); 六、看一下例子 先看一下kotlin中的类 package net.println.kotlin.chapter4 /** * @author:wangdong * @description:伴生对象和静态成员 */ fun main(args: Array<String>) { //val a = minOf(args[0].toInt(),args[1].toInt()) //用一下下面的定义 val latitude = Latitude.ofDouble(40.3) val latitude2 = Latitude.ofLatitude(latitude) println(Latitude.TAG) } /**定义一个纬度类*/ class Latitude private constructor(val value: Double){ //类的伴生对象 companion object { //定义一个静态方法 @JvmStatic fun ofDouble(double: Double): Latitude { return Latitude(double) } //定义一个静态方法 @JvmStatic fun ofLatitude(latitude: Latitude): Latitude { return Latitude(latitude.value) } //定义一个静态变量 @JvmField val TAG: String = "hello" } } 看一下Java中写法 package net.println.kotlin.chapter4; /** * @author:wangdong * @description:在java中调用Latitude方法 */ public class StaticJava { Integer a = Integer.valueOf(3); public static void main(String[] args) { //需要调用一下companion,在调用方法 Latitude latitude = Latitude.Companion.ofDouble(54.4); //可以在Latitude中方法上加一个注解@JvmStatic Latitude latitude2 = Latitude.ofDouble(54.87); System.out.println(Latitude.TAG); } } 结束

优秀的个人博客,低调大师

类加载时机与过程 asdfsadfasdfsa ...

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/79612719 通过之前的介绍可知,类加载过程共有5个步骤,分别是:加载、验证、准备、解析、初始化。其中,验证、准备、解析称为连接。下面详细介绍这5个过程JVM所做的工作。 加载 注意:“加载”是“类加载”过程的第一步,千万不要混淆。 1. 加载的过程 在加载过程中,JVM主要做3件事情: 通过一个类的全限定名来获取这个类的二进制字节流,即class文件:在程序运行过程中,当要访问一个类时,若发现这个类尚未被加载,并满足类初始化时机的条件时,就根据要被初始化的这个类的全限定名找到该类的二进制字节流,开始加载过程。 将二进制字节流的存储结构转化为特定的数据结构,存储在方法区中; 在内存中创建一个java.lang.Class类型的对象:接下来程序在运行过程中所有对该类的访问都通过这个类对象,也就是这个Class类型的类对象是提供给外界访问该类的接口。 2. 从哪里加载? JVM规范对于加载过程给予了较大的宽松度。一般二进制字节流都从已经编译好的本地class文件中读取,此外还可以从以下地方读取: 从压缩包中读取如:Jar、War、Ear等。 从其它文件中动态生成如:从JSP文件中生成Class类。 从数据库中读取将二进制字节流存储至数据库中,然后在加载时从数据库中读取。有些中间件会这么做,用来实现代码在集群间分发。 从网络中获取从网络中获取二进制字节流。典型就是Applet。 3. 类 和 数组加载过程的区别? 数组也有类型,称为“数组类型”。如: String[] str = new String[10]; 1 这个数组的数组类型是Ljava.lang.String,而String只是这个数组中元素的类型。 当程序在运行过程中遇到new关键字创建一个数组时,由JVM直接创建数组类,再由类加载器创建数组中的元素类。 而普通类的加载由类加载器完成。既可以使用系统提供的引导类加载器,也可以使用用户自定义的类加载器。 4. 加载过程的注意点 JVM规范并未给出类在方法区中存放的数据结构类完成加载后,二进制字节流就以特定的数据结构存储在方法区中,但存储的数据结构是由虚拟机自己定义的,JVM规范并没有指定。 JVM规范并没有指定Class对象存放的位置在二进制字节流以特定格式存储在方法区后,JVM会创建一个java.lang.Class类型的对象,作为本类的外部接口。既然是对象就应该存放在堆内存中,不过JVM规范并没有给出限制,不同的虚拟机根据自己的需求存放这个对象。HotSpot将Class对象存放在方法区。 加载阶段和连接阶段是交叉的通过之前的介绍可知,类加载过程中每个步骤的开始顺序都有严格限制,但每个步骤的结束顺序没有限制。也就是说,类加载过程中,必须按照如下顺序开始:加载、连接、初始化,但结束顺序无所谓,因此由于每个步骤处理时间的长短不一就会导致有些步骤会出现交叉。 验证 验证阶段比较耗时,它非常重要但不一定必要,如果所运行的代码已经被反复使用和验证过,那么可以使用-Xverify:none参数关闭,以缩短类加载时间。 1. 验证的目的是什么? 验证是为了保证二进制字节流中的信息符合虚拟机规范,并没有安全问题。 2. 为什么需要验证? 虽然Java语言是一门安全的语言,它能确保程序猿无法访问数组边界以外的内存、避免让一个对象转换成任意类型、避免跳转到不存在的代码行,如果出现这些情况,编译无法通过。也就是说,Java语言的安全性是通过编译器来保证的。 但是我们知道,编译器和虚拟机是两个独立的东西,虚拟机只认二进制字节流,它不会管所获得的二进制字节流是哪来的,当然,如果是编译器给它的,那么就相对安全,但如果是从其它途径获得的,那么无法确保该二进制字节流是安全的。通过上文可知,虚拟机规范中没有限制二进制字节流的来源,那么任意来源的二进制字节流虚拟机都能接受,为了防止字节流中有安全问题,因此需要验证! 3. 验证的过程 文件格式验证这个阶段主要验证输入的二进制字节流是否符合class文件结构的规范。二进制字节流只有通过了本阶段的验证,才会被允许存入到方法区中。本验证阶段是基于二进制字节流的,而后面的三个验证阶段都是在方法区中进行,并基于类特定的数据结构的。通过上文可知,加载开始前,二进制字节流还没进方法区,而加载完成后,二进制字节流已经存入方法区。而在文件格式验证前,二进制字节流尚未进入方法区,文件格式验证通过之后才进入方法区。也就是说,加载开始后,立即启动了文件格式验证,本阶段验证通过后,二进制字节流被转换成特定数据结构存储至方法区中,继而开始下阶段的验证和创建Class对象等操作。这个过程印证了:加载和验证是交叉进行的。 元数据验证本阶段对方法区中的字节码描述信息进行语义分析,确保其符合Java语法规范。 字节码验证本阶段是验证过程的最复杂的一个阶段。本阶段对方法体进行语义分析,保证方法在运行时不会出现危害虚拟机的事件。 符号引用验证本阶段验证发生在解析阶段,确保解析能正常执行。 准备 准备阶段完成两件事情:1. 为已经在方法区中的类中的静态成员变量分配内存类的静态成员变量也存储在方法区中。2. 为静态成员变量设置初始值初始值为0、false、null等。 示例1: public static String name = "柴毛毛"; 1 在准备阶段,JVM会在方法区中为name分配内存空间,并赋上初始值null。给name赋上”柴毛毛”是在初始化阶段完成的。 示例2: public static final String name = "柴毛毛"; 1 被final修饰的常量如果有初始值,那么在编译阶段就会将初始值存入constantValue属性中,在准备阶段就将constantValue的值赋给该字段。 解析 解析阶段是虚拟机将常量池中的符号引用替换为直接引用的过程。 初始化 初始化阶段就是执行类构造器clinit()的过程。clinit()方法由编译器自动产生,收集类中static{}代码块中的类变量赋值语句和类中静态成员变量的赋值语句。在准备阶段,类中静态成员变量已经完成了默认初始化,而在初始化阶段,clinit()方法对静态成员变量进行显示初始化。 初始化过程的注意点 clinit()方法中静态成员变量的赋值顺序是根据Java代码中成员变量的出现的顺序决定的。 静态代码块能访问出现在静态代码块之前的静态成员变量,无法访问出现在静态代码块之后的成员变量。 静态代码块能给出现在静态代码块之后的静态成员变量赋值。 构造函数init()需要显示调用父类构造函数,而类的构造函数clinit()不需要调用父类的类构造函数,因为虚拟机会确保子类的clinit()方法执行前已经执行了父类的clinit()方法。 如果一个类/接口中没有静态代码块,也没有静态成员变量的赋值操作,那么编译器就不会生成clinit()方法。 接口也需要通过clinit()方法为接口中定义的静态成员变量显示初始化。 接口中不能使用静态代码块。 接口在执行clinit()方法前,虚拟机不会确保其父接口的clinit()方法被执行,只有当父接口中的静态成员变量被使用到时才会执行父接口的clinit()方法。 虚拟机会给clinit()方法加锁,因此当多条线程同时执行某一个类的clinit()方法时,只有一个方法会被执行,其它的方法都被阻塞。并且,只要有一个clinit()方法执行完,其它的clinit()方法就不会再被执行。因此,在同一个类加载器下,同一个类只会被初始化一次。

优秀的个人博客,低调大师

JAVA线程sleep与wait区别

sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。 wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。 测试代码: public class MyThread1 implements Runnable { /* * 由于这里的MyThread1和下面的MyThread2内部run方法要用同一对象作为监视器,我们这里不能用this,因为在MyThread2里面的this和这个MyThread1的this不是同一个对象。 * 我们用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。 */ public void run() { synchronized (MutiThread.class) { System.out.println("进入MyThread1..."); System.out.println("MyThread1 is waiting..."); try { // 释放锁有两种方式,第一种方式是程序自然离开监视器的范围,也就是离开了synchronized关键字管辖的代码范围,另一种方式就是在synchronized关键 // 字管辖的代码内部调用监视器对象的wait方法。这里,使用wait方法释放锁。 MutiThread.class.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("结束MyThread1..."); } } } public class MyThread2 implements Runnable { public void run() { synchronized (MutiThread.class) { System.out.println("进入MyThread2..."); System.out.println("MyThread2 通知别的线程可以释放wait状态"); // 由于notify方法并不释放锁,即使MyThread2调用下面的sleep方法休息了10毫秒, //但MyThread1仍然不会执行,因为MyThread2没有释放锁,所以MyThread1无法得不到锁。 MutiThread.class.notify(); System.out.println("MyThread2 睡眠10秒"); try { for(int i=1;i<=10;i++){ System.out.println("睡觉"+i+"秒"); Thread.sleep(1000); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("结束MyThread2"); } } } public class MutiThread { public static void main(String[] args) { new Thread(new MyThread1()).start(); new Thread(new MyThread2()).start(); } } 运行结果: 进入MyThread1...MyThread1 is waiting...进入MyThread2...MyThread2 通知别的线程可以释放wait状态MyThread2 睡眠10秒睡觉1秒睡觉2秒睡觉3秒睡觉4秒睡觉5秒睡觉6秒睡觉7秒睡觉8秒睡觉9秒睡觉10秒结束MyThread2结束MyThread1...

优秀的个人博客,低调大师

java浅克隆与深克隆

概念:俗话就是拷贝一个副本 一般实现: 实现Cloneable 接口重写clone()方法 部分代码 public Object clone() { Object o = null; try { o = (Student) super.clone();// Object中的clone()识别出你要复制的是哪一 // 个对象。 } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } 注意:浅复制不能同时复制引用 如果需要复制引用将需要引用的对象也克隆一下做深复制 更好的方法是利用序列化(常说的串行化)来实现深复制(不需要实现Cloneable接口,需要实现Serializable接口) 见部分代码 public Object deepClone() throws IOException, OptionalDataException, ClassNotFoundException { // 将对象写到流里 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(this); // 从流里读出来 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); } 本文转自 www19 51CTO博客,原文链接:http://blog.51cto.com/doujh/1932919,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android 获取屏幕尺寸与密度

from://http://blog.csdn.net/ithomer/article/details/6688883 android中获取屏幕的长于宽,参考了网上有很多代码,但结果与实际不符,如我的手机是i9000,屏幕大小是480*800px,得到的结果却为320*533 结果很不靠谱,于是自己写了几行代码,亲测一下 测试参数: 测试环境: i9000(三星) 物理屏幕:480*800px density :1.5 测试代码: [java] view plain copy print ? //获取屏幕密度(方法1) intscreenWidth=getWindowManager().getDefaultDisplay().getWidth();//屏幕宽(像素,如:480px) intscreenHeight=getWindowManager().getDefaultDisplay().getHeight();//屏幕高(像素,如:800p) Log.e(TAG+"getDefaultDisplay","screenWidth="+screenWidth+";screenHeight="+screenHeight); //获取屏幕密度(方法2) DisplayMetricsdm=newDisplayMetrics(); dm=getResources().getDisplayMetrics(); floatdensity=dm.density;//屏幕密度(像素比例:0.75/1.0/1.5/2.0) intdensityDPI=dm.densityDpi;//屏幕密度(每寸像素:120/160/240/320) floatxdpi=dm.xdpi; floatydpi=dm.ydpi; Log.e(TAG+"DisplayMetrics","xdpi="+xdpi+";ydpi="+ydpi); Log.e(TAG+"DisplayMetrics","density="+density+";densityDPI="+densityDPI); screenWidth=dm.widthPixels;//屏幕宽(像素,如:480px) screenHeight=dm.heightPixels;//屏幕高(像素,如:800px) Log.e(TAG+"DisplayMetrics(111)","screenWidth="+screenWidth+";screenHeight="+screenHeight); //获取屏幕密度(方法3) dm=newDisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); density=dm.density;//屏幕密度(像素比例:0.75/1.0/1.5/2.0) densityDPI=dm.densityDpi;//屏幕密度(每寸像素:120/160/240/320) xdpi=dm.xdpi; ydpi=dm.ydpi; Log.e(TAG+"DisplayMetrics","xdpi="+xdpi+";ydpi="+ydpi); Log.e(TAG+"DisplayMetrics","density="+density+";densityDPI="+densityDPI); intscreenWidthDip=dm.widthPixels;//屏幕宽(dip,如:320dip) intscreenHeightDip=dm.heightPixels;//屏幕宽(dip,如:533dip) Log.e(TAG+"DisplayMetrics(222)","screenWidthDip="+screenWidthDip+";screenHeightDip="+screenHeightDip); screenWidth=(int)(dm.widthPixels*density+0.5f);//屏幕宽(px,如:480px) screenHeight=(int)(dm.heightPixels*density+0.5f);//屏幕高(px,如:800px) Log.e(TAG+"DisplayMetrics(222)","screenWidth="+screenWidth+";screenHeight="+screenHeight); 结果如下: [java] view plain copy print ? E/==MyScreenActivity===================================getDefaultDisplay(8509):screenWidth=320;screenHeight=533 E/==MyScreenActivity===================================DisplayMetrics(8509):xdpi=156.3077;ydpi=157.51938 E/==MyScreenActivity===================================DisplayMetrics(8509):density=1.0;densityDPI=160 E/==MyScreenActivity===================================DisplayMetrics(111)(8509):screenWidth=320;screenHeight=533 E/==MyScreenActivity===================================DisplayMetrics(8509):xdpi=234.46153;ydpi=236.27907 E/==MyScreenActivity===================================DisplayMetrics(8509):density=1.5;densityDPI=240 E/==MyScreenActivity===================================DisplayMetrics(222)(8509):screenWidthDip=320;screenHeightDip=533 E/==MyScreenActivity===================================DisplayMetrics(222)(8509):screenWidth=480;screenHeight=800 分析结果: 在onDraw()方法中 方法1和2,得到的结果都一致,均为320*533,明显不是测试机i9000的屏幕大小 方法3,将方法1和2得到的结果,乘以density后,完美的480*800,perfect! 注:density 大于1的情况下,需要设置targetSdkVersion在4-9之间,例如 <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="10" /> 但是,这就说明方法3一定是通用的吗? 回答是否定的,因为我也在模拟器、HTC G14物理机,以及ViewSonic、Galaxy平板上测试过,方法3在density=1.5时,放大了实际屏幕值,例如:HTC G14 在HTC G14上,实际屏幕大小,直接通过dm.widthPixels、dm.heightPixels便得到了实际物理屏幕大小(540,960) 导致无法通过一种通用的方法获取真实物理屏幕大小的原因,可能就是因为Android系统开源,不同的手机生产厂商没有统一的制造标准,来规定手机屏幕。 仔细分析代码,发现问题出在代码: getWindowManager().getDefaultDisplay().getMetrics(dm) Initialize a DisplayMetricsobject from this display's data. dm = getResources().getDisplayMetrics() Return thecurrent display metricsthat are in effect for this resource object. The returned object should be treated as read-only. 测试源码 本文转自wanqi博客园博客,原文链接:http://www.cnblogs.com/wanqieddy/p/4170011.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册