00:00
刚才我们对skyla代码进行了编译和执行,那么大家其实发现了它跟Java代码的编译执行其实是非常类似的,都是先通过编译器编译生成一个点class自解码文件,然后在JVM上直接解释执行,这里边的区别只是在于我们对于Java源文件进行编译的时候用的是Java编译器Java c,然后执行的时候呢,用的是Java命令,直接去执行自页码文件就可以了,而skyla的源文件我们编译的时候用的是skyla c编译器,然后呢,生成自页码文件是用skyla去直接执行的,那大家会发现这里边skyla编译之后的结果有一个非常奇怪的特点。就是它生成的呢,不像Java那样一个类直接生成的,对应的就是一个字节码文件,而我们现在生成的是两个点class文件,一个是hello scla,另外一个叫hello scla Dollar,这两个自解码文件又是干什么的呢?他们分别跟我们之前Java的那种。
01:04
情况有什么不同呢?这就涉及到它的底层的一些机制了,我们可以在这里给大家做一个扩展来研究一下,深入研究一下它内部的一些逻辑那。首先我们想到啊,关于自解码文件,它其实GVM看到一个自解码文件,它并不去考虑这到底是Java编译器生成的,还是skyla编译器生成的,诶它都是一样,直接解释执行就完了嘛,所以大家就想到了,那既然我们这里hello scla.class这已经是自解码文件了,那我们能用skyva去做执行,那可以用Java去直接执行吗?这其实我们自然想到应该也是可以的啊,第我接下来直接阿va去运行一下试试。但大家发现报错了,这里面报的错误呢,比较奇怪,他说的是有一个类没有被找到。这个类是scla下边的p Dollar。
02:01
啊,那当然了,大家就会发现Java里边既然肯定就没有对应的这个scla这样的一个包,然后下边的pre Dollar这样的类了啊,所以我们要执行的时候,如果用skyla去执行的时候,它可能在SKY的SDK里边有这样的一个类,那么就可以正常执行,Java里边不包含,那当然就执行通不过了,但是这里边大家会发现有点奇怪,我们的源代码里边并没有写出来pre Dollar这样的一个东西啊,我们这里边就是非常简单的一个main方法,里边print line怎么会涉及到printiff Dollar呢?我们看到这样一个特殊的Dollar符号,那自然就想到,诶,刚才不是编译生成两个字解码文件吗?另外一个这个就叫做hello sc Dollar后面加了一个Dollar,那难道他们俩之间有什么关系吗?诶,那接下来我们再尝试,既然这个也是一个自解码文件,那我们尝试啊,这个自解码文件用Java直接去做一个执行。
03:00
大家会发现这个就更不靠谱了,说我们当前这个类里边并没有static的main方法,诶,所以这里边我们并不能直接去执行啊,就对于这个Java类而言,我们必须要有一个static的main方法,然后才能在外部直接去执行嘛,啊,所以这里边会发现这个自建码文件就不是直接可以去执行的,所以我们自然就有了这样一个想法,我们前边直接Java去执行hello scalela这个入口是对的。我们的入口类,或者说入口的这个字节码啊,对应的其实就是hello sc.class而另外的hello scla dollar.class是干什么呢?主要应该是做了一些辅助的工作,那他们之间。到底又分别是干了一些什么事情,到底应该是有哪些具体的这个逻辑和流程呢?为了考虑的更加的详细,我们就需要对这两个字节码文件做一个反编译了。那我们这里边需要用到一个编译工具。
04:05
我们可以把生成的自解码文件拖进来,然后接下来就可以看到啊,利用这个反编译工具把它在反编译成Java代码,我们看一看它到底实现的逻辑是什么样的,当然了,这里边大家需要注意,我们由于生成的这个自解码文件是scalela编译之后得到的自解码文件,而现在呢,又是把这个自解码文件再翻译成了Java代码,诶,所以这个过程大家可能会发现它是有一有一些可能比较不匹配,比较看起来比较怪异的地方的,甚至有一些地方可能根本都不符合Java的语法结构,这个大家也不要觉得奇怪,我们只要了解这个逻辑就可以了。好,那接下来我们首先看一下这个hello scla.class它的反编译结果,这个不出预料啊,啊,大家看到这就是一个final class,就叫做hellola。然后在这个。
05:00
类里边呢,有一个public static的main方法,这个main方法里边,哦,大家看到这里边,我们本来想的直接调就应该调这里吗?那应该就直接print line直接打印就可以了,但他并没有直接打印,而是。哦,我们看这里边又是一个方法调用,它调用的是什么呢?诶,这里有一个hello scla点,呃,这是反反编译工具对这一个底层代码解析的不够正确啊,其实这个点表示的大家看还有这个下划线啊,这其实表示的是就是hello sc Dollar。啊,所以这里边其实要调的是hello scalela Dollar,如果我们把它当成一个类的话,是调它下边的,呃,静态的对象或者静态的方法,后面是点,然后呢,它里边又有一个module Dollar,所以我们自然想到了这可能是它下边的一个静态属性,静态对象,调这个对象的下面有一个main方法,然后把当前的参数直接传进来,哎,所以大家发现我们执行这个print line的时候,它并不是直接在hello scla的main方法里面调用的。
06:09
而是他又找到了hello sc Dollar这个类里边的其他的方法。啊,这里面就稍微有一点绕了,前面我们提到hello sc Dollar主要就做辅助工作,那所以接下来我们就要看它里边到底是哪些东西。这个代码里边,这个类里边,我们看首先也是一个final class啊,但是它里边的代码呢,就会比较诡异了,我们可能发现这个根本不符合我们一般呃想象当中的Java语法啊,呃,这这里就主要是因为这个SC代码在编译之后,再经过反编译,主要是差别体现在了这里啊,大家只要了解它的基本逻辑就可以了,那我们首先看一下,在上边直接来了一个public static model Dollar。那所以大家看,这不就是我们想想到的这个类里边有一个静态的属性吗?而而这个属性到底又是什么东西呢?我们看一下后边它的整体逻辑,后边有一个static,一个静态代码块,然后直接来了一个new,啊,这个很奇怪,并不符合我们Java的语法规则,但是我们应该能想到他是要干什么呢?
07:17
其实就是要new一个当前hellokela Dollar自身的一个对象。而且是在静态代码块里边去拗,那大家想这就相当于是一个静态对象吧。啊,然后接下来我们看到那扭出来的这个静态对象又跟module Dollar有什么关系呢?我们发现下边有一个private的hello scale Dollar,它的构造方法。这是一个私有化的构造方法,在这个构造方法里边,把module Dollar让它赋值等于了this。诶,那当前的这个this又是什么呢?大家看前面,这不是直接静态代码块里面拗了一个对象出来吗?所以显然它的逻辑就是把自己在静态代码块里拗出来的对象。
08:03
一个静态的对象付给了当前的module Dollar。大家如果要是仔细思考一下的话,这其实这这叫做什么呀?这就是构造方法私有化,然后我们再直接定义一个静态对象,在这里边直接定义的这个静态对象,这不就相当于是单例设计模式吗?诶,所以如果结合我们一开始在scda里边写的这个原文件,大家再思考一下,跟Java代码里边最显著的一个不同其实是什么呢?除了语法规则,细细小的一些语法点之外,那大家其实会发现了,其实就是一开始我们声明的时候,Hello scla就不是一个类,就不是一个class。我们声明的它是一个对象object。那其实这里面大家就会想到,诶,那我们声明的是一个对象object,那它到底是谁的对象呢?既然我们面对对象,他应该都有都有。
09:01
基于哪个类去创建对象嘛,呃,那所以这里边我们就可以解决这样一个问题了,当前我们声明的其实是一个对象,这个对象如果要翻译成Java的代码,应该怎么写呢?那其实应该专门有一个类里边要去。相当于啊,我们就做这样的一个单立设计模式,去生成一个静态的对象,这样后边我们调用的时候,全局就只有这么一份,就不会再去重复生成啊同样的对象了,我们当前的这个需求,当前的这一个类,不也就是相当于全局只有一份吗?啊,当前的这个对象我们就是直接调用调它的这个main方法去处理,里边打印这个控制台信息就可以了,所以这个逻辑大家发现在scla里边啊,它就用这个object,他去掉了Java里边静态的这样一个关键字,Static这样一个关键字,而使用object关键字声明这样的一个单例对象。啊,那在scla的底层语法里边啊,其实这样声明的这个object,往往概念上是把它叫做半生对象。
10:10
因为我们我们知道对象不能真正意义上的单独出现,它应该还是有,到底是哪个类的对象,那当前这个哈斯kla到底又是谁的对象呢?通过反编译之后的这个结果,我们可以看得很明显,它其实应该是hello scla Dollar的一个对象,对吧?啊,它这里边直接在里边拗了一个自身的这个对象,然后呢,呃,这是作为一个全局的静态对象出现的,而且后面我们就会发现在真正调用这个。想要去打印输出一行信息的时候,前面我们调的是hello scalela Dollar这个类里边的module Dollar这个静态对象的mainin方法,哎,所以大家看到这里边也有一个main方法,但是它并不是static静态的,所以这里边你不能直接调。
11:00
不能直接在外部去直接执行啊,只能是在呃,我们这里边的hello scla这里边去做这个对象的调用,对吧?诶,所以这里边就直接点儿may掉这个方法,而这个main方法的具体执行用到了这里的pre点,其实就是pre Dollar,用到了pre dollar.module Dollar下边的print line这个方法啊,所以前面我们说为什么用Java直接去执行的时候说找不到predict Dollar这样一个类呢?因为这里边我们要从scla的SDK里边把这个类引进来,接下来才能调用它下面的printline方法。这就是这个完整的执行过程。啊,所以大家可能会觉得有点奇怪,就是在SKY里边,为什么他要把这个事情弄得这么复杂呢?不像Java里边那么简单,就一个类,大家看到这里边。本身我们就是一个原文件,一个类,然后就直接生成一个点class文件,然后有一个入口的静态的main方法,然后去执行不就完了吗?呃,其实大家会发现啊,盖LA的设计思想,它其实是什么呢?在Java之前我们这种执行的过程当中。
12:09
它其实是定义了一个类,然后就执行它里边的静态方法了。那对于对于面对对象要求很高的人来讲,就会觉得这不足够面对对象啊。哎,你不是说我我们当前的这个世界里边是一切皆对象吗?那你为什么这个方法它本来也应该是一个对象的方法调用,你怎么能直接用一个类就直接去。调用这样一个方法了呢,那他也应该继续对象啊,所以在scla里边去掉了static关键字,那但是我又想实现对应的这个功能啊,我想实现,哎,全局就只有这么一份,我直接要调用,那怎么办呢?那我就实现一个单立设计模式,我就有一个类,然后它里边呢,只有一份静态的对象,我在调用对应的方法的时候,原先我们定义的那个静态方法的时候,就相当于是调用这个静态对象里边的方法。
13:07
哎,所以大家看这个绕了一圈,用这种方式实现了在Java里边的static静态的这样一个功能,这就是skyla代码底层的一个执行逻辑。啊,那有了前面的这些分析,大家就会发现,那假如说现在我们想要用Java直接去执行这个hello sc这样一个。Skyla的,呃,原文件编译出来的程序啊,这样可以去执行吗?当然也是没有问题的,我们直接Java,只要在引入对应的对应的类库不就完了吗?CP啊,把这个class pass引入进来,我们现在要的还可以直接利用这个系统里边的环境变量。另外一边我们定义过sky home。后要下边的Li目录library库目录啊,下边的scalela library把它做一个引入啊,后面这里是一个分号,大家需要注意一下啊,然后接下来直接执行hello盖了,你看这样就完全没有问题了啊,所以这就是我们完整的关于这一个底层两个点class文件的一个一个分析的过程啊,那么在概念上来讲,我们说一般情况我们会把生成的这两个class文件。
14:33
对应的这这两个类啊,反编译出来的这两个类,我们可以做一个解释,就是真正意义上的这个hello scalela,那这是我们这最后要执行程序的时候的那个入口的那个类啊,那这个类叫做什么呢?我们前面说tla里边不是说这个object,我们把它叫做伴生对象吗?哎,所以我们那么它半生它相伴相生,跟谁相伴相生呢?它就是跟对应的这个啊,相当于我们的这个入口的这个类啊,叫做同样名字的这个类相伴相生。
15:07
大家要注意它俩是相伴相生,但是这里的object这个hello scla对象并不是hello scla这个类的对象,是谁的对象呢?其实是hello scla Dollar里边单独定义的一个静态对象,对吧?啊,所以如果我们严格要去做区分的话,有时候就会把它叫做这个类,我们把它认为是。伴生对象的伴生类,而hello scla Dollar呢?我们可以把它叫做伴生对象的所属类啊,这就是相关的一些概念,给大家做一个扩展,可以对于底层有更深刻的理解。
我来说两句