该语言设计主要来源于java,下面只说一下不同的地方,其他没有说明的默认和java是一样的。
设计的改动
支持动态类型
当类定义上添加@Dynamic
注解时,操作这个类的属性就像javascript对象一样,能在编译后运行中给这个类添加属性或方法。
其实不用大动干戈,只需要维护一个map即可实现,只不过可以通过反射获取。
支持函数式编程
如果一个文件直接定义变量和方法,那么该变量和方法会被加载到类Static中。
A.java
void aaa(){
print(111);
}
调用Static类中的方法时,Static可以省略,即Static.abc(),可以直接abc()。并且在使用时,是默认导入这个Static类的,任何地方都可以直接就使用,并且不用使用Static.方法
。
B.java
void bbb(){
aaa();
}
编程便利性的改动
提供官方仓库
提供官方仓库,并自带库管理工具,类似maven、npm,可以安装同一个库的不同版本,可以全局安装也可以在项目内安装,所以官方仓库的依赖库都必须写明自己依赖的其他库的名称和版本(类似必须有一个npm的package.json文件),编译器在编译时将自动提示哪些库版本冲突,是哪些库共同引入导致的冲突。
拥有更方便和强大的反射机制
所有的泛型信息都可以通过反射获取。
所有的注解信息都可以通过反射获取。
动态类型通过Class层只能获取在类里定义的结构,但是通过对象层可以获取所有的动态添加的属性和方法。
示例:
Class dc=MyDynamic.class;//这样获取的Class,获取不到动态属性和方法
Class dc=new MyDynamic().getClass();//这样获取的Class,可以获取动态属性和方法
变量名即字符串
实例变量的变量名,可以通过类名.__fields.变量名
获取,这是非常强大的功能,数据库查询时,数据库改字段时,再也不用到处改了。
类名.__fields
其实是虚拟机为这个类生成的枚举。
支持给方法参数设置默认值
void show(Integer i=0,String s="")
print(i+s);
能检测出类型的,无需定义类型
a=10;//等价于Integer a=new Integer(10),等价于Integer a=10,编译器会自定将整数类型转成Integer,小数类型转成Float
a=new User();//等价于User a=new User()
a={1,2,3};//等价于 List<Integer> a={1,2,3}
a={"a":1,"b":2,"c":3};//等价于 Map<String,Integer> a={"a":1,"b":2,"c":3}
在生成返回值将变得非常实用:
Map<String,Integer> m(){
return {"a":1,"b":2,"c":3};//不需要new,当然使用new Map{"a":1,"b":2,"c":3}也是正确的写法。
}
支持多重赋值
Integer i,String s=10,"str";
允许多返回值
用逗号分隔返回类型即可。
Integer,String mReturn(){
return 1,"s";
}
public static main(List s){
Integer age,String name=mReturn();
}
map支持对应多个value
map支持对应多个value,想对应多少value,就在泛型上定义多少value。
Map<String,Integer,Integer> map={"key1":10:11,"key2":20:21}//定义一个key两个value的map并且添加两个键值对
Map<String,Integer,Integer> map={};//定义一个key两个value的空map
map.put("kk1",10,20);
Integer age,Integer height=map.get("kk1");
支持多行字符串代码编写方式
不需要作死的用+
拼接
String s="ss
sssss
";
支持字符串内自动转义
使用三个双引号即可。
String s="""ss
"1"+"2"="3"
sssss
""";
对象可以直接作为判断条件
如果引用为null则为false,如果非null为true;
Object obj=null;
if(obj)
print(obj);
官方仓库提供IOC和AOP拓展库支持
提供一个精简版的spring,只保留最核心的功能,别搞什么生命周期、作用域、三级缓存了,我们不需要。
可不能让spring这个庞然大物入侵这门新语言。
语法的改动
干掉原生类型
取消原生类型,全部用基础类代替。基础类型又移除了Short、Long、Double。
基础类型:Object,Byte,Integer,Float,List,Map,String,Boolean,Char,Array,Enum。其中Integer是Java中的Long(真正被移除的是Short和Integer),Float是java中的Double(真正被移除的是Float)。
以上这些基础类型,有点像java的包装类,是在虚拟机层面支持的类型,除了Object,其他类型在定义这些类型时,不必使用new(基础类型和其他类型唯一的区别就在这里)。
如:
Byte a=1;
Integer b=2;
List<Integer> list=1,2,3;
List<Integer> list={1,2,3};
List<Integer> list={};//定义一个空list
List<Integer> list=new List{1,2,3};
Array<Integer> array=[4];//定义长度为4的integer空数组
Array<Integer> array=[4]{};//定义长度为4的integer空数组
Array<Integer> array=new Array[4];
Array<Integer> array=1,2,3;//定义长度为3的并且已经赋值的integer数组
Array<Integer> array={1,2,3};//定义长度为3的并且已经赋值的integer数组
Array<Integer> array=new Array{1,2,3};
Map<String,Integer> map="a":1,"b":2,"c":3;
Map<String,Integer> map={"a":1,"b":2,"c":3};
Map<String,Integer> map=new Map{"a":1,"b":2,"c":3}
Map<String,Integer> map={};//定义一个空map
基础类除了不用new和其他类没有任何区别,==能被继承!==除了final方法不能重写之外,其他方法可以重写。
String内部实现伪代码
class String{
const final Array<Byte> value;
String(Array<Byte> value){
this.value=value;
}
}
访问修饰符统一public
取消所有访问修饰符,全部都是public。
取消原因:既然private都能通过反射调用,搞修饰符有何意义?而且每次都get,set调用属性你不嫌烦我还嫌徒增开发量和代码量。
提供属性的取值和赋值的钩子方法
由于取消的访问修饰符,写get和set就没有意义了。
但必须提供属性的取值和赋值的钩子方法,示例:
class A{
int a;
__getA(){//两个下划线开头的get或set方法是系统提供的钩子,除了类内部,外部所有的new A().a都会触发这个钩子,不用定义返回值,get方法自动检测属性本身的类型
return a+1;
}
__setA(a){//setA也是同理,__get或__set方法是隐藏的,外面看不见也无法显示调用。
this.a=a;
}
}
接口
接口不能定义类变量,只能定义方法。
接口必有至少一个方法。
方法可以有默认实现(java也有),且无需加default关键字(java要加default)。
interface A{
void aaa(){
print("my is default...");
}
}
之前java的没有方法的接口,全部改为注解形式。
这样做是为了将接口和注解的功能完全区分开来,注解就专注于打标签,接口就专注于定义公共方法,不要混淆了。
增强break标签
break标签
能在方法内使用,不单单只是在循环中可以用,且只能往后跳到一个标记处,且标记不能超出方法的作用域范围。
类似java的break标签
,但不限于在循环内使用。
void m(j=10){
for(i=0;i<100;i++){
if(i==j){
break A;
}
print(i+"run...");
}
print("end...");//这句代码会被跳过
A: //跳到这里
print("over...");//这句代码会被执行
}
void m(j=10){
if(j==0){
break A;
}
for(i=0;i<100;i++){
print(i+"run...");
}
print("end...");
A: //跳到这里
print("over...");//这句代码会被执行
}
增加const关键字
const关键字只能用来修饰变量,指示这个变量内部结构不能修改(只管一层,深层的对象修改不管),可以和final一起使用。
const Map<String,Integer> map={"key1":10,"key2":20}//map里的值不能修改,也不能添加和删除元素
const Student stu=new Student("zhangsan",20);//stu里的属性不能修改,即使是动态类型也不能添加和删除属性
增加instanceof使用范围
instanceof可以用于判断实例对象与类、接口、注解、枚举的继承关系,不校验泛型。
当一个类定义上有某个注解时,它的实例对象instanceof该注解时会返回true。
增加typeof关键字
typeof可以用于判断Class对象与类、接口、注解、枚举的继承关系,并且是严格校验泛型的。
进制
默认10进制
2进制:数字开头使用2_
8进制:数字开头使用8_
16进制:数字开头使用16_
以此类推。
枚举
枚举是特殊的类,使用继承Enum类定义:
class A extends Enum{
Q,W,E,R;
}
允许枚举继承枚举:
class B extends A{
A,B,C,D;
}
参考java枚举,使用时和java枚举是一样的。
toString方法
toString方法默认返回当前对象的标准json格式的字符串,无需自己写。
省略{}后必须正确缩进
省略{}和java类似,但增加一个要求是,省略后结构体内的代码缩进必须像python一样(只管原{}作用域内的,且只管一层,里面深层的缩进不管)。
//正确案例
void m{
for(true)
print(1);
print(2);//只要是正确缩进的都算{}作用域内,所以这句代码时for作用域内,会循环打印
}
//错误案例
void m{
for(true)
print(1);
}
//错误案例
void m{
for(true) print(1);
}
//错误案例
void m{
for(true)
print(1);
print(2);//不会报错,但这句代码不在循环体内
}
lambda表达式
一、支持java8的写法
二、新增写法
和java8的lambda表达式类似,只需以下改动
1.把java8的省略的写法全部干掉。
2.不需要使用->
。
3.小括号前面必须带上方法名。
4.可以支持实现多个方法。
5.返回值可以定义也可以不定义。
new Thread(run(){print("run...")}).start();
interface P{
void aaa(Integer i);
String bbb(String s);
String,Map<String,Intger> ccc(String s,Integer i);
}
class Stu{
Stu(P p){
}
}
new Stu(
aaa(Integer i){print("aaa..."+i)}
,bbb(String s){print("bbb..."+s);return "bbb..."+s;}
,String,Map<String,Intger> ccc(String s,Integer i){return "ccc",{"a":1};}
);
干掉swith
去除swith,用if:
代替
if:
里的所有花括号{}
可以省略(但省略后需要遵守正确的缩进)。
if:xx{//类型没有校验,任何类型都可以作为"if:"的判断条件
:1{//默认是等号判断,":1"和":=1"都一样的效果
print(1);//默认会break,如果不想break,需要手动continue
}
:<=2{
print(2);
continue;
}
:>3{
print(3);
break;//默认会break,写不写break都一样的效果
}
:{
print("默认");
}
}
干掉while
去除while,用for代替
for(true){
}
for(;true;){
}
//上面这两种写法等同
干掉synchronized和notify和wait
全部用Lock代替。
干掉volatile
用注解@Volatile
和@NotVolatile
代替。
所有变量默认都是volatile的,如果要开启重排序,需要在虚拟机启动参数设置,一旦设置就是所有变量都是可以重排序的。
干掉transient
用注解@Rransient
代替。