‘壹’ 什么是源代码啊
源代码
源程序是指未编译的文本代码。
验证码主要是为防止暴利破解,所以需要防止图片识别。所以验证码一般情况下为书写不正规,且有随机的背景杂点,或杂线
源代码(也称源程序),是指一系列人类可读的计算机语言指令。
在现代程序语言中,源代码可以是以书籍或者磁带的形式出现,但最为常用的格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码的最终目的是将人类可读的文本翻译成为计算机可以执行的二进制指令,这种过程叫做编译,通过编译器完成。
作用
源代码主要功用有如下2种作用:
生成目标代码,即计算机可以识别的代码。
对软件进行说明,即对软件的编写进行说明。为数不少的初学者,甚至少数有经验的程序员都忽视软件说明的编写,因为这部分虽然不会在生成的程序中直接显示,也不参与编译。但是说明对软件的学习、分享、维护和软件复用都有巨大的好处。因此,书写软件说明在业界被认为是能创造优秀程序的良好习惯,一些公司也硬性规定必须书写。
需要指出的是,源代码的修改不能改变已经生成的目标代码。如果需要目标代码做出相应的修改,必须重新编译。
代码组合
源代码作为软件的特殊部分,可能被包含在一个或多个文件中。一个程序不必用同一种格式的源代码书写。例如,一个程序如果有C语言库的支持,那么就可以用C语言;而另一部分为了达到比较高的运行效率,则可以用汇编语言编写。
较为复杂的软件,一般需要数十种甚至上百种的源代码的参与。为了降低种复杂度,必须引入一种可以描述各个源代码之间联系,并且如何正确编译的系统。在这样的背景下,修订控制系统(RCS)诞生了,并成为研发者对代码修订的必备工具之一。
还有另外一种组合:源代码的编写和编译分别在不同的平台上实现,专业术语叫做软件移植。
版权
如果按照源代码类型区分软件,通常被分为两类:自由软件和非自由软件。自由软件一般是不仅可以免费得到,而且公开源代码;相对应地,非自由软件则是不公开源代码。所有一切通过非正常手段获得非自由软件源代码的行为都将被视为非法。
质量
对于计算机而言,并不存在真正意义上的“好”的源代码;然而作为一个人,好的书写习惯将决定源代码的好坏。源代码是否具有可读性,成为好坏的重要标准。软件文档则是表明可读性的关键。
效率
虽然我们可以通过不同的语言来实现计算机的同一功能,但在执行效率上则存在不同。普遍规律是:越高级的语言,其执行效率越低。这也是为什么汇编语言生成的文件比用VB语言生成文件普遍要小的原因。
‘贰’ 急求C语言编译的小游戏(如扫雷),附带源代码和注释。
扫雷游戏(c语言版)
已经编译运行确认了:
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
#define LEFTPRESS 0xff01
#define LEFTCLICK 0xff10
#define LEFTDRAG 0xff19
#define MOUSEMOVE 0xff08
struct
{
int num;/*格子当前处于什么状态,1有雷,0已经显示过数字或者空白格子*/
int roundnum;/*统计格子周围有多少雷*/
int flag;/*右键按下显示红旗的标志,0没有红旗标志,1有红旗标志*/
}Mine[10][10];
int gameAGAIN=0;/*是否重来的变量*/
int gamePLAY=0;/*是否是第一次玩游戏的标志*/
int mineNUM;/*统计处理过的格子数*/
char randmineNUM[3];/*显示数字的字符串*/
int Keystate;
int MouseExist;
int MouseButton;
int MouseX;
int MouseY;
void Init(void);/*图形驱动*/
void MouseOn(void);/*鼠标光标显示*/
void MouseOff(void);/*鼠标光标隐藏*/
void MouseSetXY(int,int);/*设置当前位置*/
int LeftPress(void);/*左键按下*/
int RightPress(void);/*鼠标右键按下*/
void MouseGetXY(void);/*得到当前位置*/
void Control(void);/*游戏开始,重新,关闭*/
void GameBegain(void);/*游戏开始画面*/
void DrawSmile(void);/*画笑脸*/
void DrawRedflag(int,int);/*显示红旗*/
void DrawEmpty(int,int,int,int);/*两种空格子的显示*/
void GameOver(void);/*游戏结束*/
void GameWin(void);/*显示胜利*/
int MineStatistics(int,int);/*统计每个格子周围的雷数*/
int ShowWhite(int,int);/*显示无雷区的空白部分*/
void GamePlay(void);/*游戏过程*/
void Close(void);/*图形关闭*/
void main(void)
{
Init();
Control();
Close();
}
void Init(void)/*图形开始*/
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
}
void Close(void)/*图形关闭*/
{
closegraph();
}
void MouseOn(void)/*鼠标光标显示*/
{
_AX=0x01;
geninterrupt(0x33);
}
void MouseOff(void)/*鼠标光标隐藏*/
{
_AX=0x02;
geninterrupt(0x33);
}
void MouseSetXY(int x,int y)/*设置当前位置*/
{
_CX=x;
_DX=y;
_AX=0x04;
geninterrupt(0x33);
}
int LeftPress(void)/*鼠标左键按下*/
{
_AX=0x03;
geninterrupt(0x33);
return(_BX&1);
}
int RightPress(void)/*鼠标右键按下*/
{
_AX=0x03;
geninterrupt(0x33);
return(_BX&2);
}
void MouseGetXY(void)/*得到当前位置*/
{
_AX=0x03;
geninterrupt(0x33);
MouseX=_CX;
MouseY=_DX;
}
void Control(void)/*游戏开始,重新,关闭*/
{
int gameFLAG=1;/*游戏失败后判断是否重新开始的标志*/
while(1)
{
if(gameFLAG)/*游戏失败后没判断出重新开始或者退出游戏的话就继续判断*/
{
GameBegain(); /*游戏初始画面*/
GamePlay();/*具体游戏*/
if(gameAGAIN==1)/*游戏中重新开始*/
{
gameAGAIN=0;
continue;
}
}
MouseOn();
gameFLAG=0;
if(LeftPress())/*判断是否重新开始*/
{
MouseGetXY();
if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)
{
gameFLAG=1;
continue;
}
}
if(kbhit())/*判断是否按键退出*/
break;
}
MouseOff();
}
void DrawSmile(void)/*画笑脸*/
{
setfillstyle(SOLID_FILL,YELLOW);
fillellipse(290,75,10,10);
setcolor(YELLOW);
setfillstyle(SOLID_FILL,BLACK);/*眼睛*/
fillellipse(285,75,2,2);
fillellipse(295,75,2,2);
setcolor(BLACK);/*嘴巴*/
bar(287,80,293,81);
}
void DrawRedflag(int i,int j)/*显示红旗*/
{
setcolor(7);
setfillstyle(SOLID_FILL,RED);
bar(198+j*20,95+i*20,198+j*20+5,95+i*20+5);
setcolor(BLACK);
line(198+j*20,95+i*20,198+j*20,95+i*20+10);
}
void DrawEmpty(int i,int j,int mode,int color)/*两种空格子的显示*/
{
setcolor(color);
setfillstyle(SOLID_FILL,color);
if(mode==0)/*没有单击过的大格子*/
bar(200+j*20-8,100+i*20-8,200+j*20+8,100+i*20+8);
else
if(mode==1)/*单击过后显示空白的小格子*/
bar(200+j*20-7,100+i*20-7,200+j*20+7,100+i*20+7);
}
void GameBegain(void)/*游戏开始画面*/
{
int i,j;
cleardevice();
if(gamePLAY!=1)
{
MouseSetXY(290,70); /*鼠标一开始的位置,并作为它的初始坐标*/
MouseX=290;
MouseY=70;
}
gamePLAY=1;/*下次按重新开始的话鼠标不重新初始化*/
mineNUM=0;
setfillstyle(SOLID_FILL,7);
bar(190,60,390,290);
for(i=0;i<10;i++)/*画格子*/
for(j=0;j<10;j++)
DrawEmpty(i,j,0,8);
setcolor(7);
DrawSmile();/*画脸*/
randomize();__page_break__
for(i=0;i<10;i++)/*100个格子随机赋值有没有地雷*/
for(j=0;j<10;j++)
{
Mine[i][j].num=random(8);/*如果随机数的结果是1表示这个格子有地雷*/
if(Mine[i][j].num==1)
mineNUM++;/*现有雷数加1*/
else
Mine[i][j].num=2;
Mine[i][j].flag=0;/*表示没红旗标志*/
}
sprintf(randmineNUM,"%d",mineNUM); /*显示这次总共有多少雷数*/
setcolor(1);
settextstyle(0,0,2);
outtextxy(210,70,randmineNUM);
mineNUM=100-mineNUM;/*变量取空白格数量*/
MouseOn();
}
void GameOver(void)/*游戏结束画面*/
{
int i,j;
setcolor(0);
for(i=0;i<10;i++)
for(j=0;j<10;j++)
if(Mine[i][j].num==1)/*显示所有的地雷*/
{
DrawEmpty(i,j,0,RED);
setfillstyle(SOLID_FILL,BLACK);
fillellipse(200+j*20,100+i*20,7,7);
}
}
void GameWin(void)/*显示胜利*/
{
setcolor(11);
settextstyle(0,0,2);
outtextxy(230,30,"YOU WIN!");
}
int MineStatistics(int i,int j)/*统计每个格子周围的雷数*/
{
int nNUM=0;
if(i==0&&j==0)/*左上角格子的统计*/
{
if(Mine[0][1].num==1)
nNUM++;
if(Mine[1][0].num==1)
nNUM++;
if(Mine[1][1].num==1)
nNUM++;
}
else
if(i==0&&j==9)/*右上角格子的统计*/
{
if(Mine[0][8].num==1)
nNUM++;
if(Mine[1][9].num==1)
nNUM++;
if(Mine[1][8].num==1)
nNUM++;
}
else
if(i==9&&j==0)/*左下角格子的统计*/
{
if(Mine[8][0].num==1)
nNUM++;
if(Mine[9][1].num==1)
nNUM++;
if(Mine[8][1].num==1)
nNUM++;
}
else
if(i==9&&j==9)/*右下角格子的统计*/
{
if(Mine[9][8].num==1)
nNUM++;
if(Mine[8][9].num==1)
nNUM++;
if(Mine[8][8].num==1)
nNUM++;
}
else if(j==0)/*左边第一列格子的统计*/
{
if(Mine[i][j+1].num==1)
nNUM++;
if(Mine[i+1][j].num==1)
nNUM++;
if(Mine[i-1][j].num==1)
nNUM++;
if(Mine[i-1][j+1].num==1)
nNUM++;
if(Mine[i+1][j+1].num==1)
nNUM++;
}
else if(j==9)/*右边第一列格子的统计*/
{
if(Mine[i][j-1].num==1)
nNUM++;
if(Mine[i+1][j].num==1)
nNUM++;
if(Mine[i-1][j].num==1)
nNUM++;
if(Mine[i-1][j-1].num==1)
nNUM++;
if(Mine[i+1][j-1].num==1)
nNUM++;
}
else if(i==0)/*第一行格子的统计*/
{
if(Mine[i+1][j].num==1)
nNUM++;
if(Mine[i][j-1].num==1)
nNUM++;
if(Mine[i][j+1].num==1)
nNUM++;
if(Mine[i+1][j-1].num==1)
nNUM++;
if(Mine[i+1][j+1].num==1)
nNUM++;
}
else if(i==9)/*最后一行格子的统计*/
{
if(Mine[i-1][j].num==1)
nNUM++;
if(Mine[i][j-1].num==1)
nNUM++;
if(Mine[i][j+1].num==1)
nNUM++;
if(Mine[i-1][j-1].num==1)
nNUM++;
if(Mine[i-1][j+1].num==1)
nNUM++;
}
else/*普通格子的统计*/
{
if(Mine[i-1][j].num==1)
nNUM++;
if(Mine[i-1][j+1].num==1)
nNUM++;
if(Mine[i][j+1].num==1)
nNUM++;
if(Mine[i+1][j+1].num==1)
nNUM++;
if(Mine[i+1][j].num==1)
nNUM++;
if(Mine[i+1][j-1].num==1)
nNUM++;
if(Mine[i][j-1].num==1)
nNUM++;
if(Mine[i-1][j-1].num==1)
nNUM++;
}__page_break__
return(nNUM);/*把格子周围一共有多少雷数的统计结果返回*/
}
int ShowWhite(int i,int j)/*显示无雷区的空白部分*/
{
if(Mine[i][j].flag==1||Mine[i][j].num==0)/*如果有红旗或该格处理过就不对该格进行任何判断*/
return;
mineNUM--;/*显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利*/
if(Mine[i][j].roundnum==0&&Mine[i][j].num!=1)/*显示空格*/
{
DrawEmpty(i,j,1,7);
Mine[i][j].num=0;
}
else
if(Mine[i][j].roundnum!=0)/*输出雷数*/
{
DrawEmpty(i,j,0,8);
sprintf(randmineNUM,"%d",Mine[i][j].roundnum);
setcolor(RED);
outtextxy(195+j*20,95+i*20,randmineNUM);
Mine[i][j].num=0;/*已经输出雷数的格子用0表示已经用过这个格子*/
return ;
}
/*8个方向递归显示所有的空白格子*/
if(i!=0&&Mine[i-1][j].num!=1)
ShowWhite(i-1,j);
if(i!=0&&j!=9&&Mine[i-1][j+1].num!=1)
ShowWhite(i-1,j+1);
if(j!=9&&Mine[i][j+1].num!=1)
ShowWhite(i,j+1);
if(j!=9&&i!=9&&Mine[i+1][j+1].num!=1)
ShowWhite(i+1,j+1);
if(i!=9&&Mine[i+1][j].num!=1)
ShowWhite(i+1,j);
if(i!=9&&j!=0&&Mine[i+1][j-1].num!=1)
ShowWhite(i+1,j-1);
if(j!=0&&Mine[i][j-1].num!=1)
ShowWhite(i,j-1);
if(i!=0&&j!=0&&Mine[i-1][j-1].num!=1)
ShowWhite(i-1,j-1);
}
void GamePlay(void)/*游戏过程*/
{
int i,j,Num;/*Num用来接收统计函数返回一个格子周围有多少地雷*/
for(i=0;i<10;i++)
for(j=0;j<10;j++)
Mine[i][j].roundnum=MineStatistics(i,j);/*统计每个格子周围有多少地雷*/
while(!kbhit())
{
if(LeftPress())/*鼠标左键盘按下*/
{
MouseGetXY();
if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)/*重新来*/
{
MouseOff();
gameAGAIN=1;
break;
}
if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/
{
j=(MouseX-190)/20;/*x坐标*/
i=(MouseY-90)/20;/*y坐标*/
if(Mine[i][j].flag==1)/*如果格子有红旗则左键无效*/
continue;
if(Mine[i][j].num!=0)/*如果格子没有处理过*/
{
if(Mine[i][j].num==1)/*鼠标按下的格子是地雷*/
{
MouseOff();
GameOver();/*游戏失败*/
break;
}
else/*鼠标按下的格子不是地雷*/
{
MouseOff();
Num=MineStatistics(i,j);
if(Num==0)/*周围没地雷就用递归算法来显示空白格子*/
ShowWhite(i,j);
else/*按下格子周围有地雷*/
{
sprintf(randmineNUM,"%d",Num);/*输出当前格子周围的雷数*/
setcolor(RED);
outtextxy(195+j*20,95+i*20,randmineNUM);
mineNUM--;
}
MouseOn();
Mine[i][j].num=0;/*点过的格子周围雷数的数字变为0表示这个格子已经用过*/
if(mineNUM<1)/*胜利了*/
{
GameWin();
break;
}
}
}
}
}
if(RightPress())/*鼠标右键键盘按下*/
{
MouseGetXY();
if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/
{
j=(MouseX-190)/20;/*x坐标*/
i=(MouseY-90)/20;/*y坐标*/
MouseOff();
if(Mine[i][j].flag==0&&Mine[i][j].num!=0)/*本来没红旗现在显示红旗*/
{
DrawRedflag(i,j);
Mine[i][j].flag=1;
}
else
if(Mine[i][j].flag==1)/*有红旗标志再按右键就红旗消失*/
{
DrawEmpty(i,j,0,8);
Mine[i][j].flag=0;
}
}
MouseOn();
sleep(1);
}
}
}
‘叁’ java源代码编译的时候怎么处理注释部分的
所谓的编译就是把高级的语言翻译成计算机可以识别的机器语言,所以当编译程序编译到注释那段的时候程序也会把它编译成机器码的形似存储在内存里,但是这个机器码并不会执行,如果你学过汇编你就会知道它们的存储空间是不一样的
‘肆’ Java编译时注解和运行时注解有什么区别
重写,重载,泛型,分别是在运行时还是编译时执行的
1. 方法重载是在编译时执行的,因为,在编译的时候,如果调用了一个重载的方法,那么编译时必须确定他调用的方法是哪个。如:
当调用evaluate("hello")时候,我们在编译时就可以确定他调用的method #1.
2.
方法的重写是在运行时进行的。这个也常被称为运行时多态的体现。编译器是没有办法知道它调用的到底是那个方法,相反的,只有在jvm执行过程中,才知晓到底是父子类中的哪个方法被调用了当有如下一个接口的时候,我们是无法确定到底是调用父类还是子类的方法
3.
泛型(类型检测),这个发生在编译时。编译器会在编译时对泛型类型进行检测,并吧他重写成实际的对象类型(非泛型代码),这样就可以被JVM执行了。这个过程被称为"类型擦除"。
类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。
类型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。类型擦除的主要过程如下:
1). 将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
2). 移除所有的类型参数。
在编译后变成:
4. 注解。注解即有可能是运行时也有可能是编译时。
如java中的@Override注解就是典型的编译时注解,他会在编译时会检查一些简单的如拼写的错误(与父类方法不相同)等
同样的@Test注解是junit框架的注解,他是一个运行时注解,他可以在运行时动态的配置相关信息如timeout等。
5. 异常。异常即有可能是运行时异常,也有可能是编译时异常。
RuntimeException是一个用于指示编译器不需要检查的异常。RuntimeException
是在jvm运行过程中抛出异常的父类。对于运行时异常是不需要再方法中显示的捕获或者处理的。
已检查的异常是被编译器在编译时候已经检查过的异常,这些异常需要在try/catch块中处理的异常。
6. AOP. Aspects能够在编译时,预编译时以及运行时使用。
1).
编译时:当你拥有源码的时候,AOP编译器(AspectJ编译器)能够编译源码并生成编织后的class。这些编织进入的额外功能是在编译时放进去的。
2). 预编译时:织入过程有时候也叫二进制织入,它是用来织入到哪些已经存在的class文件或者jar中的。
3). 运行时:当被织入的对象已经被加载如jvm中后,可以动态的织入到这些类中一些信息。
7. 继承:继承是编译时执行的,它是静态的。这个过程编译后就已经确定
8. 代理(delegate):也称动态代理,是在运行时执行。
‘伍’ 源码是什么意思啊
源码指编写的最原始程序的代码。
用户平时使用软件时就是程序把“源码”翻译成我们可直观的形式表现出来供用户使用的。任何一个网站页面,换成源码就是一堆按一定格式书写的文字和符号。
源码主要功用
1、生成目标代码,即计算机可以识别的代码。
2、对软件进行说明,即对软件的编写进行说明。为数不少的初学者,甚至少数有经验的程序员都忽视软件说明的编写,因为这部分虽然不会在生成的程序中直接显示,也不参与编译。
但是说明对软件的学习、分享、维护和软件复用都有巨大的好处。因此,书写软件说明在业界被认为是能创造优秀程序的良好习惯,一些公司也硬性规定必须书写。
(5)源码和编译注解扩展阅读:
计算机里面运行的所有东西都是用程序编出来的,而编写程序要用到计算机语言,用计算机语言直接编出来的程序就叫源码,比如用VisualBasic编写的源码文件一般为.bas文件,而用C++编写的一般为.cpp文件,源代码不能直接运行,必须编译后才能运行。源码经过编译处理后就可以直接在操作系统下运行了。
从字面意义上来讲,源文件是指一个文件,指源代码的集合.源代码则是一组具有特定意义的可以实现特定功能的字符(程序开发代码)。“源代码”在大多数时候等于“源文件”。
‘陆’ c语言程序编译时,注释部分会参加编译吗,会出现在目标程序中吗
不会的,因为注释被忽略了。
C语言的原型ALGOL60语言(也称为A语言)。
1963年,剑桥大学将ALGOL60语言发展成为CPL(CombinedProgrammingLanguage)语言。
1967年,剑桥大学的MatinRichards对CPL语言进行了简化,于是产生了BCPL语言。
1970年,美国贝尔实验室的KenThompson将BCPL进行了修改,并为它起了一个有趣的名字“B语言”。意思是将CPL语言煮干,提炼出它的精华。并且他用B语言写了第一个UNIX操作系统。
‘柒’ java开发中常用的注解有哪些
Java 注解全面解析,学习java做一个java工程师不但待遇高,而且前途无可限量。为什么这样说呢?因为java程序语言作为最流行的计算机开发语言之一,几乎所有的系统、软件、app、网页等都是需要用到java的。
1.基本语法
注解定义看起来很像接口的定义。事实上,与其他任何接口一样,注解也将会编译成class文件。
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {}
除了@符号以外,@Test的定义很像一个空的接口。定义注解时,需要一些元注解(meta-annotation),如@Target和@Retention
@Target用来定义注解将应用于什么地方(如一个方法或者一个域)
@Retention用来定义注解在哪一个级别可用,在源代码中(source),类文件中(class)或者运行时(runtime)
在注解中,一般都会包含一些元素以表示某些值。当分析处理注解时,程序可以利用这些值。没有元素的注解称为标记注解(marker annotation)
四种元注解,元注解专职负责注解其他的注解,所以这四种注解的Target值都是ElementType.ANNOTATION_TYPE
注解 说明
@Target 表示该注解可以用在什么地方,由ElementType枚举定义
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
ANNOTATION_TYPE:注解声明(应用于另一个注解上)
TYPE_PARAMETER:类型参数声明(1.8新加入)
TYPE_USE:类型使用声明(1.8新加入)
PS:当注解未指定Target值时,此注解可以使用任何元素之上,就是上面的类型
@Retention 表示需要在什么级别保存该注解信息,由RetentionPolicy枚举定义
SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机(JVM)中)
RUNTIME:VM将在运行期也保留注解信息,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息)
PS:当注解未定义Retention值时,默认值是CLASS
@Documented 表示注解会被包含在javaapi文档中
@Inherited 允许子类继承父类的注解
2. 注解元素
– 注解元素可用的类型如下:
– 所有基本类型(int,float,boolean,byte,double,char,long,short)
– String
– Class
– enum
– Annotation
– 以上类型的数组
如果使用了其他类型,那编译器就会报错。也不允许使用任何包装类型。注解也可以作为元素的类型,也就是注解可以嵌套。
元素的修饰符,只能用public或default。
– 默认值限制
编译器对元素的默认值有些过分挑剔。首先,元素不能有不确定的值。也就是说,元素必须要么具有默认值,要么在使用注解时提供元素的值。
其次,对于非基本类型的元素,无论是在源代码中声明,还是在注解接口中定义默认值,都不能以null作为值。这就是限制,这就造成处理器很难表现一个元素的存在或缺失状态,因为每个注解的声明中,所有的元素都存在,并且都具有相应的值。为了绕开这个限制,只能定义一些特殊的值,例如空字符串或负数,表示某个元素不存在。
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface MockNull {
public int id() default -1;
public String description() default “”;
}
3. 快捷方式
何为快捷方式呢?先来看下springMVC中的Controller注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
String value() default “”;
}
可以看见Target应用于类、接口、注解和枚举上,Retention策略为RUNTIME运行时期,有一个String类型的value元素。平常使用的时候基本都是这样的:
@Controller(“/your/path”)
public class MockController { }
这就是快捷方式,省略了名-值对的这种语法。下面给出详细解释:
注解中定义了名为value的元素,并且在应用该注解的时候,如果该元素是唯一需要赋值的一个元素,那么此时无需使用名-值对的这种语法,而只需在括号内给出value元素所需的值即可。这可以应用于任何合法类型的元素,当然了,这限制了元素名必须为value。
4. JDK1.8注解增强
TYPE_PARAMETER和TYPE_USE
在JDK1.8中ElementType多了两个枚举成员,TYPE_PARAMETER和TYPE_USE,他们都是用来限定哪个类型可以进行注解。举例来说,如果想要对泛型的类型参数进行注解:
public class AnnotationTypeParameter<@TestTypeParam T> {}
那么,在定义@TestTypeParam时,必须在@Target设置ElementType.TYPE_PARAMETER,表示这个注解可以用来标注类型参数。例如:
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestTypeParam {}
ElementType.TYPE_USE用于标注各种类型,因此上面的例子也可以将TYPE_PARAMETER改为TYPE_USE,一个注解被设置为TYPE_USE,只要是类型名称,都可以进行注解。例如有如下注解定义:
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {}
那么以下的使用注解都是可以的:
List<@Test Comparable> list1 = new ArrayList<>();
List<? extends Comparable> list2 = new ArrayList<@Test Comparable>();
@Test String text;
text = (@Test String)new Object();
java.util. @Test Scanner console;
console = new java.util.@Test Scanner(System.in);
PS:以上@Test注解都是在类型的右边,要注意区分1.8之前的枚举成员,例如:
@Test java.lang.String text;
在上面这个例子中,显然是在进行text变量标注,所以还使用当前的@Target会编译错误,应该加上ElementType.LOCAL_VARIABLE。
@Repeatable注解
@Repeatable注解是JDK1.8新加入的,从名字意思就可以大概猜出他的意思(可重复的)。可以在同一个位置重复相同的注解。举例:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Filter {
String [] value();
}
如下进行注解使用:
@Filter({“/admin”,”/main”})
public class MainFilter { }
换一种风格:
@Filter(“/admin”)
@Filter(“/main”)
public class MainFilter {}
在JDK1.8还没出现之前,没有办法到达这种“风格”,使用1.8,可以如下定义@Filter:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Filters.class)
public @interface Filter {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Filters {
Filter [] value();
}
实际上这是编译器的优化,使用@Repeatable时告诉编译器,使用@Filters来作为收集重复注解的容器,而每个@Filter存储各自指定的字符串值。
JDK1.8在AnnotatedElement接口新增了getDeclaredAnnotationsByType和getAnnotationsByType,在指定@Repeatable的注解时,会寻找重复注解的容器中。相对于,getDeclaredAnnotation和getAnnotation就不会处理@Repeatable注解。举例如下:
@Filter(“/admin”)
@Filter(“/filter”)
public class FilterClass {
public static void main(String[] args) {
Class<FilterClass> filterClassClass = FilterClass.class;
Filter[] annotationsByType = filterClassClass.getAnnotationsByType(Filter.class);
if (annotationsByType != null) {
for (Filter filter : annotationsByType) {
System.out.println(filter.value());
}
}
System.out.println(filterClassClass.getAnnotation(Filter.class));
}
}
日志如下:
/admin
/filter
null
望采纳!
‘捌’ JAVA中: 编译过的代码和源代码的区别是
源代码就是你在电脑里手敲进去的那些;
编译过的代码其实是你的编译软件将你手敲进去的那些代码“翻译”成了计算机可以识别读懂的机器语言,换句话说也就是一堆二进制的代码。
你写程序的时候会用到某种软件(比如java的eclipse,.NET的vs2005、vs2008等),当你要编译时只需点下软件的编译按钮,软件会自动给你编译。
‘玖’ 问下计算机大神,C语言编译执行时会自动去掉源代码的注释符,那么这个去掉是有规则的还是无规则的亦或
一般情况下是不会反编译出来的,但也有例外。
c语言是在预处理阶段把所有的注释全部干掉的。编译器不接受任何注释,会直接报错。
如果你的IDE能提供一个类似于插件之类的工具,在c程序提交编译之前自动把你所有的注释变进程序正文中做成那种由双引号标识的字符串(例如添加一条语句char * _comm_1="Built on 2013-11-11";),而且之后没有使用类似于混淆器这样的防止反编译的技术,那么对软件反汇编后是可以看到它们的。
但是正常情况下别人是不可能直接从软件反编译的结果上去找你的程序注释的。
‘拾’ { /* compiled code */ },一些源码的方法内部会有这样的注释。是什么意思。。
就是开发人员加的注释,方便自己或者他人维护和理解代码,编译器编译的时候会自动忽略。
/* */中间可以是中文或其它语言,不同语言会有不同的注释语法。