首页 文章 精选 留言 我的

精选列表

搜索[骁龙8至尊版],共10033篇文章
优秀的个人博客,低调大师

PHP学习8——图像处理

主要内容: 加载GD库 创建图像 绘制点,线,矩形,多边形,椭圆,弧线 绘制文字 通过GD库生成验证码 其实吧,学习图像方法的最大作用,好像就是为了制作验证码。 所以此专题,不如叫做制作验证码。 1、加载GD库 PHP5不仅可以处理文本数据,还可以处理多种格式的图像,安装了GD库,需要通过php.ini来加载GD库。 可以通过phpinfo()方法来确认,如果有gd栏目就说明GD库加载成功了。 phpinfo.php <?php phpinfo(); ?> 2、创建图像 GD库处理图像的操作都是先在内存处理,操作完成后再以数据流的方式输出到浏览器,有4个步骤: 创建画布 绘制图像 输出图像 释放资源 创建画布 创建画布就是在内存区中开辟一块存储区 imagecreate.php <?php //创建普通画布 $img1=imagecreate(100,100) or die("创建普通画布失败<br/>"); echo "创建普通画布成功<br/>"; //创建真彩画布 $img2=imagecreatetruecolor(200,300) or die("创建真彩画布失败<br/>"); echo "创建真彩画布成功<br/>"; //获取图像的大小 echo "图像1的x:".imagesx($img1)."<br/>"; echo "图像1的y:".imagesy($img1)."<br/>"; echo "图像2的x:".imagesx($img2)."<br/>"; echo "图像2的y:".imagesy($img2)."<br/>"; ?> 输出 创建普通画布成功 创建真彩画布成功 图像1的x:100 图像1的y:100 图像2的x:200 图像2的y:300 其他的方法常用: imagecreatefromgif()通过gif文件或者url新建一个图像 imagecreatefromjpeg()通过JPEG文件或者url新建一个图像 imagecreatefrompng()通过png或者url新建一个图像 imagecreatefrombmp()通过bmp或者url新建一个图像 输出图像 imagegif($image,$filename)输出一个gif格式图像到浏览器,如果第二个参数指定了,则以文件形式输出 imagejpeg($image,$filename) imagepng($image,$filename) imageoutput.php <?php //创建画布 $image1=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image2=imagecreatefrompng("C:/xampp/htdocs/1.png");//使用本地资源 //在输出图像之前清理输出缓冲,否则缓冲中有其他字符串,图像会乱码 ob_clean(); //指定输出类型为图像,否则乱码,chrome,Firefox,Opera等浏览器不兼容 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image1) or die("创建图像失败<br/>"); imagejpeg($image2) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image1,$image2); ?> 输出 一些方法说明: ob_clean();用于清理输出缓冲,否则缓冲中有其他字符串会使得图片乱码,最后变为2进制数据 header("Content-type:image/jpeg");指定输出类型为图像,是为了解决浏览器的兼容性问题,否则乱码,chrome,Firefox,Opera等浏览器不兼容,只有IE兼容。 imagedestroy($image1);用于释放资源,让出内存。 设置颜色 前面已经学习了如何建立一张画布,但是没有“彩笔”,绘画就还没有开始,下面来创建“彩笔”,设置颜色。 imagecolorallocate($image,$red,$green,$blue),会返回一个标识,代表了给定的RGB成分组成的颜色。 imagecolorallocate.php <?php //创建画布 $image=imagecreate(200,200); //第一次设置的通常为背景色 $red=imagecolorallocate($image,255,0,0); //设置画笔为蓝色 $blue=imagecolorallocate($image,0,0,255); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 区域填充 imagefill($image,$x,$y,$color)它会将(x,y)点出颜色相同并且相邻颜色替换为$color设置的颜色。 这里使用rand(0,255)产生一个大于等于0,小于255的随机数来设置颜色。 imagefill.php <?php //创建画布 $image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 //第一次设置的通常为背景色 $rand=imagecolorallocate($image,rand(0,255),rand(0,255),rand(0,255));//使用随机数设置颜色 //设置画笔为蓝色 //$blue=imagecolorallocate($image,0,0,255); //区域填充 imagefill($image,10,10,$rand); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 绘制点,线,矩形,多边形,椭圆,弧线 点和线 imagesetpixel($image,$x,$y,$color)在(x,y)位置使用$color颜色绘制点 imageline($image,$x1,$y1,$x2,$y2,$color)在(x1,y1)到(x2,y2)位置使用$color颜色绘制线 利用下面的这段代码可以在生成验证码的时候生成干扰元素。 imagesetpixel_line.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(200,200); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为蓝色 $white=imagecolorallocate($image,255,255,255); //绘制点 for($i=0;$i<1000;$i++){ imagesetpixel($image,rand(0,200),rand(0,200),$white); } //绘制线 for($i=0;$i<10;$i++){ imageline($image,rand(0,200),rand(0,200),rand(0,200),rand(0,200),$white); } //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 矩形 imagerectangle($image,$x1,$y1,$x2,$y2,$color)绘制矩形 imagefilledrectangle($image,$x1,$y1,$x2,$y2,$color)填充矩形 rectangle.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(300,300); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为蓝色 $white=imagecolorallocate($image,255,255,255); //绘制矩形 imagerectangle($image,10,10,100,100,$white); //填充矩形 imagefilledrectangle($image,50,50,100,100,$white); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 多边形 imagepolygon($image,$arr_points,$num_points,$color)绘制多边形,$arr_points多边形顶点数组数必须大于等于$num_points定点总数 imagefilledpolygon($image,$arr_points,$num_points,$color)填充多边形 imagepolygon.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(300,300); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为蓝色 $white=imagecolorallocate($image,255,255,255); $arr_points=array(10,10,50,20,40,30,100,120,200,30,30,150); //绘制多边形 imagepolygon($image,$arr_points,6,$white); //填充多边形 imagefilledpolygon($image,$arr_points,5,$white); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 绘制椭圆 imageellipse($image,$cx,$cy,$width,$height,$color)绘制椭圆 imagefilledellipse($image,$cx,$cy,$width,$height,$color)绘制椭圆 imageellipse.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(300,300); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为蓝色 $white=imagecolorallocate($image,255,255,255); //绘制椭圆 imageellipse($image,100,100,200,100,$white); //填充椭圆 imagefilledellipse($image,100,100,200,100,$white); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 绘制弧线 imagearc($image,$cx,$cy,$width,$height,$start,$end,$color)绘制弧线,$start是开始角度,$end是结束角度 imagefilledarc($image,$cx,$cy,$width,$height,$start,$end,$color,$mode)填充弧线,$start是开始角度,$end是结束角度 imagearc.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(300,300); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为蓝色 $white=imagecolorallocate($image,255,255,255); //绘制椭圆 imagearc($image,100,100,200,200,0,90,$white); //填充椭圆 imagefilledarc($image,100,100,200,200,0,45,$white,IMG_ARC_PIE); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 绘制文字 imagestring($image,$font,$x,$y,$data,$color)水平绘制一行字符串,使用$font字体(内置字体为1,2,3,4,5)写$data内容,(x,y)位置为内容左上角。 imagestringup($image,$font,$x,$y,$data,$color)垂直绘制一行字符串 imagechar($image,$font,$x,$y,$data,$color)水平绘制一个字符 imagecharup($image,$font,$x,$y,$data,$color)垂直绘制一个字符 imagettftext($image,$size,$angle,$x,$y,$color,$fontfile,$text)使用truetype字体向图像写入文本 使用$font字体(内置字体为1,2,3,4,5),如果使用其他字体用imageloadfont() imagestring.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(300,300); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为蓝色 $white=imagecolorallocate($image,255,255,255); $data="imagestring"; //绘制文字 imagestring($image,1,100,20,$data,$white); imagestringup($image,3,30,150,$data,$white); imagestring($image,5,100,100,$data,$white); //绘制字符 imagechar($image,5,200,20,$data,$white); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 使用字库,字库文件默认在:C:\Windows\Fonts imagettftext.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(500,500); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为白色 $white=imagecolorallocate($image,255,255,255); $data="hello PHP"; //绘制truetype文字 imagettftext($image,55,0,50,250,$white,"C:/Windows/Fonts/Arial.ttf",$data); imagettftext($image,55,90,250,400,$white,"C:/Windows/Fonts/Arial.ttf",$data); imagettftext($image,55,45,100,370,$white,"C:/Windows/Fonts/Arial.ttf",$data); imagettftext($image,55,135,370,330,$white,"C:/Windows/Fonts/Arial.ttf",$data); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 输出 通过GD库生成验证码 在网上注册一些账号,常常遇到注册码输入,生成验证码步骤: 创建画布 随机绘制字符 绘制干扰元素 输出图像到浏览器 释放资源 check_data.php <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(200,100); //第一次设置的通常为背景色 $black=imagecolorallocate($image,0,0,0); //设置画笔为白色 $white=imagecolorallocate($image,255,255,255); //产生随机干扰线条 for($i=0;$i<9;$i++){ imageline($image,rand(0,200),rand(0,100),rand(0,200),rand(0,100),$white); } //产生随机干扰点 for($i=0;$i<200;$i++){ imagesetpixel($image,rand(0,200),rand(0,100),$white); } //产生4个字符的字符串 for($i=0,$data='';$i<4;$i++){ switch(rand(1,3)){ case '1':$ch=rand(0,9);break; case '2':$ch=sprintf('%c',rand(97,122));break; case '3':$ch=sprintf('%c',rand(65,90));break; } $data.=$ch; } //绘制truetype文字 imagettftext($image,32,rand(1,15),20,70,$white,"C:/Windows/Fonts/Arial.ttf",$data); //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> 可能输出 最后来一个好玩的图像 他的实现代码如下 <?php //创建画布 //$image=imagecreatefromjpeg("http://pic.58pic.com/58pic/13/19/83/30J58PICFBZ_1024.jpg");//使用网络资源 $image=imagecreate(500,500); //第一次设置的通常为背景色 $white=imagecolorallocate($image,255,255,255); //设置画笔 $black=imagecolorallocate($image,0,0,0); $data="Hello PHP!"; //绘制truetype文字 for($i=0;$i<360;$i+=5){ imagettftext($image,35,$i,250,250,$black,"C:/Windows/Fonts/Arial.ttf",$data); } //输出图像前清理输出缓冲 ob_clean(); //解决chrome兼容性问题 header("Content-type:image/jpeg"); //输出图像到浏览器 imagejpeg($image) or die("创建图像失败<br/>"); //释放资源 imagedestroy($image); ?> ok,就到这里吧。

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

JavaScript学习之旅-8(原创)

在上一篇文章中,花了很大的篇幅主要是学习了JavaScript中变量的作用域与解构赋值,这一篇主要学习JavaScript的this关键字。 说到this关键字,我们首先回顾下,在Java中,this关键字主要有以下三个作用。 (1)this调用本类中的属性,也就是指向类中的声明成员变量;比如 this.name= name;(伪代码)在方法中将形式参数name的值赋值给成员变量name (2)this调用本类中的其他方法 (3)this调用本类中的其他构造方法,调用时要放在构造方法的首行 简单说完了Java中的this,我们在说说JavaScript中的this,先写一个关于this的小demo this - 1 首先,我们定义了一个 objec的对象,然后定义 age字段的时候,我们使用的是 当前日期对象的 年 字段减去 this.birth,最后打印的结果是 2018 — 1992 = 26。 概念一: 在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是objec这个变量。所以,this.birth可以拿到objec的birth属性。 我们换一种写法, this - 2 当我们单独调用 getAge() 这个方法的时候,系统给我们打印了 NaN,可能我们就疑惑了,咦~刚才不是说函数内部如果调用了this,它始终指向当前对象吗,那为什么这里是NaN,这个this到底是指向谁? 概念二: 如果以对象的方法形式调用,比如 objec.age(),该函数的this指向被调用的对象,也就是objec,这是符合我们预期的。 如果单独调用函数,比如getAge(),此时,该函数的this指向全局对象,也就是window。 接着,你可能脑洞大开的说到,既然每一个function都是一个对象,那么我们也可以这样写: this - 3 哇塞,函数里套函数,真是甚屌的写法,然后运行看下结果 this - 4 what fuck。。。尬的一逼。我们分析下错误原因,this指针只在getYear方法的函数内指向objec 对象、在函数内部定义的函数,this又指向undefined,所以导致了这样的结果。 如何解决上述函数套函数,this指针指向问题? 解决办法一,我们可以额外用一个变量去记录this,如下图 this - 5 通过使用 use 变量来记录this,然后在具体逻辑操作通过use去使用,根据这种策略我们成功的解决了this关键字在函数内部嵌套函数的问题。当然还有第二种解决办法。 上面大致说完了this关键字的使用,那么,我们开发者能否主动控制this的指向,毕竟this可以指向undefined或window或者我们自己定义的对象。在JavaScript设计的时候,它设计了 apply 关键字来帮助我们去控制this的指向。 要指定函数的this指向哪个对象,可以用函数本身的apply方法。先上demo看下简单的效果 apply - 1 首先,getAge是一个计算年龄的函数,getAge.apply这个函数(apply翻译过来就是,适用于、应用于)apply要接收两个参数,第一个参数就是需要绑定的this变量(指向谁,指向那个对象,方便理解就是应用到那个对象),第二个参数是Array。 以此类推,this - 4(图片)关于函数套函数this指向错乱的问题,于是又多了一种解决思路。我们可以在返回值的时候,加上apply关键字让其指向objec对象即可,如下图 apply - 2 这也是解决this关键字,函数里面套函数的第二种使用方法。 值得一提的是,有一个与apply()类似的方法是call()。 1.:每个函数都包含两个非继承而来的方法:call()方法和apply()方法。 2: 相同点,这两个方法的作用是一样的 都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。 apply()与call()唯一区别是: apply()把参数打包成Array再传入; call()把参数按顺序传入。 首先看下call方法的基本使用: call 我们通过call方法里面参数的指向,指向不同的对象,所以依次打印出了所指向对象的值。 本篇文章主要学习的是关于this关键字的使用以及注意事项;apply()、call()方法的基本使用去规避指向问题,本章的基本内容就结束了。 未完待续。。。 如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。 Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

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

重拾Java(8)-反射

Java 在需要使用到某个类时会载入 .class 文档,在 JVM 产生 Java.lang.Class 实例代表该文档,从 Class 实例开始,就可以获得类的许多类型。 .class 文档反映了类基本信息,因而从 Class 等API取得类信息的方法就称为反射 一、Class与.class文档 Java 在真正需要某个类时才会加载对应的 .class 文档,而非在程序启动时就加载所有类,因为大部分时候我们只需要用到应用程序部分资源,有选择地加载可以节省系统资源 java.lang.Class 的实例代表 Java 应用程序运行时加载的 .class 文档,类、接口、Enum等编译过后,都会生成 .class 文档,所以 Class可以用来包含类、接口、Enum等信息 Class 类没有公开的构造函数,实例是由 JVM 自动产生,每个 .class 文档加载时, JVM 会自动生成对应的 Class 对象 可以通过 Object 的 getClass() 方法或者通过 .class 常量取得每个对象对应的 Class 对象。如果是基本类型,可以使用对象的包装类加载 .TYPE 取得 Class 对象 例如,使用 Integer.TYPE 可取得代表 int 基本类型的 Class,通过 Integer.class 取得代表 Integer.class 文档的 Class 在取得 Class 对象后,就可以操作 Class 对象的公开方法取得类基本信息 例如 package com.czy.demo; public class Student { public static void main(String[] args) { Class cl=Student.class; System.out.println("类名称:"+cl.getName()); System.out.println("简单类名称:"+cl.getSimpleName()); System.out.println("包名:"+cl.getPackage()); System.out.println("是否为接口:"+cl.isInterface()); System.out.println("是否为基本类型:"+cl.isPrimitive()); System.out.println("是否为数组对象:"+cl.isArray()); System.out.println("父类名称:"+cl.getSuperclass().getName()); } } 输出结果为 类名称:com.czy.demo.Student 简单类名称:Student 包名:package com.czy.demo 是否为接口:false 是否为基本类型:false 是否为数组对象:false 父类名称:java.lang.Object Java 在真正需要类时才会加载 .class 文档,即在生成对象时才会加载 .class 文档。如果只是使用类声明了一个变量,此时并不会加载.class文档,而只是让编译程序检查对应的 .class 文档是否存在 例如,在 Stduent 类中定义了 static 静态区域块,在首次加载 .class 文档时会被执行(这是默认情况下,也可以指定不执行) public class Student { static { System.out.println("载入了 Student.class 文档"); } } 再来测试加载顺序 package com.czy.demo; public class Main { public static void main(String[] args) { Student student; System.out.println("声明了 Student 变量"); student=new Student(); System.out.println("生成了 Student 实例"); } } 输出结果为 声明了 Student 变量 载入了 Student.class 文档 生成了 Student 实例 二、使用Class.forName() 在某些情况下,会存在事先不知道类名称,需要事后指定类名称来动态加载类的情况 可以使用 Class.forName() 方法实现动态加载类,用字符串指定类名称来获得类相关信息 package com.czy.demo; public class Main { public static void main(String[] args) { try{ Class cl=Class.forName("java.lang.String"); System.out.println("类名称:"+cl.getName()); System.out.println("简单类名称:"+cl.getSimpleName()); System.out.println("包名:"+cl.getPackage()); System.out.println("是否为接口:"+cl.isInterface()); System.out.println("是否为基本类型:"+cl.isPrimitive()); System.out.println("是否为数组对象:"+cl.isArray()); System.out.println("父类名称:"+cl.getSuperclass().getName()); }catch(ClassNotFoundException e){ e.printStackTrace(); } } } 输出结果 类名称:java.lang.String 简单类名称:String 包名:package java.lang, Java Platform API Specification, version 1.8 是否为接口:false 是否为基本类型:false 是否为数组对象:false 父类名称:java.lang.Object Class.forName() 另一重载版本可以指定类名称、加载类时是否执行静态区域块、类加载器 public static Class<?> forName(String name, boolean initialize, ClassLoader loader) 例如 还是使用 Student 类 package com.czy.demo; public class Student { static { System.out.println("执行静态区域块"); } } 测试调用顺序 public class Main { public static void main(String[] args) { try{ Class cl=Class.forName("com.czy.demo.Student",false,Main.class.getClassLoader()); System.out.println("已载入class文档"); Student student; System.out.println("声明了Student变量"); student=new Student(); System.out.println("生成Student实例"); }catch(ClassNotFoundException e){ e.printStackTrace(); } } } 输出结果 已载入class文档 声明了Student变量 执行静态区域块 生成Student实例 由于指定了加载类时不执行静态区域块,所以在建立了 Stduent 实例后,静态区域块才被执行。类加载器则是使用 Main.class 文档的类加载器 因此,只有一个参数的 Class.forName(String name) 方法,等同于 Class.forName(className, true, currentLoader) 即默认加载静态区域块,使用当前类的类加载器来载入类 三、从Class获得信息 Class对象代表加载的.class文档,取得Class对象后,就可以取得.class文档中记载的信息,如包、构造函数、数据成员、方法成员等 每一种信息都对有对应的类型,如包对应的类型是 java.lang.Package,构造函数对应的类型是 java.lang.reflect.Constructor 例如,先来为Student类增添多种类型的不同信息 package com.czy.demo; public final class Student { enum Gender{ male,female } private String name; public int age; protected Gender gender; public Student(String name,int age){ } public Student(String name,int age,Gender gender){ } private Student(){ } public String getName() { return name; } private int getAge(){ return age; } protected Gender getGender(){ return gender; } } 再来获取各种信息 public class Main { public static void main(String[] args) { try { Class cl = Class.forName("com.czy.demo.Student"); // 取得包对象 Package p = cl.getPackage(); System.out.println("包名:" + p.getName()); // 访问修饰符 int modifier = cl.getModifiers(); System.out.println("类访问修饰符:" + Modifier.toString(modifier)); System.out.println(); //取得构造函数信息 Constructor[] constructors=cl.getConstructors(); for(Constructor constructor:constructors){ System.out.print("访问修饰符:" + Modifier.toString(constructor.getModifiers())); System.out.print(" 构造函数名:"+constructor.getName()); System.out.println(); } System.out.println(); //取得声明的数据成员 Field[] fields = cl.getDeclaredFields(); for (Field field : fields) { System.out.print("访问修饰符:" + Modifier.toString(field.getModifiers())); System.out.print(" 类型:"+field.getType().getName()); System.out.print(" 成员名:"+field.getName()); System.out.println(); } System.out.println(); //取得成员方法息 Method[] methods=cl.getDeclaredMethods(); for(Method method:methods){ System.out.print("访问修饰符:" + Modifier.toString(method.getModifiers())); System.out.print(" 返回值类型:"+method.getReturnType().getName()); System.out.print(" 方法名:"+method.getName()); System.out.println(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 运行结果 包名:com.czy.demo 类访问修饰符:public final 访问修饰符:public 构造函数名:com.czy.demo.Student 访问修饰符:public 构造函数名:com.czy.demo.Student 访问修饰符:private 类型:java.lang.String 成员名:name 访问修饰符:public 类型:int 成员名:age 访问修饰符:protected 类型:com.czy.demo.Student$Gender 成员名:gender 访问修饰符:public 返回值类型:java.lang.String 方法名:getName 访问修饰符:private 返回值类型:int 方法名:getAge 访问修饰符:protected 返回值类型:com.czy.demo.Student$Gender 方法名:getGender 四、利用Class建立对象 如果已有确切的类,那么就可以使用new关键字建立实例。如果不知道类名称,那么可以利用Class.forName() 动态加载.class文档,取得Class对象之后,利用其newInstance()方法建立实例 Class cl=Class.forName("ClassName"); Object object=cl.newInstance(); 这种事先不知道类名称,又需要建立类实例的需求,一般情况下都是由于开发者需要得到某个类对象并对其行为进行操纵,可是该类又是由他人开发且还未完工,因此就需要来动态加载.class文档 例如,你需要来控制学生、老师或者家长的唱歌行为,可是学生、老师和家长这些类又是由其他人来设计的,你只是对开始与暂停操作进行控制 那么,你可以规定学生类必须实现Sing接口 public interface Sing { void start(); } 那么,就可以来进行自己的开发了,将动态加载的对象强转为Sing public class Main { public static void main(String[] args) { try { Sing palyer = (Sing) Class.forName("className").newInstance(); palyer.start(); } catch (Exception e) { e.printStackTrace(); } } } 然后规定他人设计的学生类必须实现Sing接口 package com.czy.demo; public class Student implements Sing { @Override public void start() { System.out.println("学生唱歌"); } } 这样,等到得到确切的类名称后,修改main方法的className即可 public static void main(String[] args) { try { Sing palyer = (Sing) Class.forName("com.czy.demo.Student").newInstance(); palyer.start(); } catch (Exception e) { e.printStackTrace(); } } 五、操作成员方法 java.lang.reflect.Method 实例是方法的代表对象,可以使用 invoke() 方法来动态调用指定的方法 例如,修改Student类,将get方法都指定为公有的,将set方法指定为私有的 package com.czy.demo; public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { System.out.println("调用了getName方法,Name:" + name); return name; } public int getAge() { System.out.println("调用了getAge方法,Age:" + age); return age; } private void setName(String name) { this.name = name; System.out.println("调用了setName方法,name:" + name); } private void setAge(int age) { this.age = age; System.out.println("调用了setAge方法,age:" + age); } } 一般情况下,类的私有方法只有在其内部才可以被调用,通过反射我们可以来突破这一限制 首先来调用公有方法 public class Main { public static void main(String[] args) throws Exception { Class cl = Class.forName("com.czy.demo.Student"); // 指定构造函数 Constructor constructor = cl.getConstructor(String.class, Integer.TYPE); // 根据指定的构造函数来获取对象 Object object = constructor.newInstance("叶", 22); // 指定方法名称来获取对应的公开的Method实例 Method getName = cl.getMethod("getName"); // 调用对象object的方法 getName.invoke(object); // 指定方法名称来获取对应的公开的Method实例 Method getAge = cl.getMethod("getAge"); // 调用对象object的方法 getAge.invoke(object); } } 输出结果如下所示,可以知道Student对象的两个get方法成功被调用了 调用了getName方法,Name:叶 调用了getAge方法,Age:22 受保护或私有方法的调用步骤略有不同 public class Main { public static void main(String[] args) throws Exception { Class cl = Class.forName("com.czy.demo.Student"); // 指定构造函数 Constructor constructor = cl.getConstructor(String.class, Integer.TYPE); // 根据指定的构造函数来获取对象 Object object = constructor.newInstance("叶", 22); // 指定方法名称来获取对应的私有的Method实例 Method setName = cl.getDeclaredMethod("setName", String.class); setName.setAccessible(true); setName.invoke(object, "新的名字"); // 指定方法名称来获取对应的私有的Method实例 Method setAge = cl.getDeclaredMethod("setAge", Integer.TYPE); setAge.setAccessible(true); setAge.invoke(object, 23); } } 输出结果如下所示,可以看到私有方法一样在外部被调用了 调用了setName方法,name:新的名字 调用了setAge方法,age:23

资源下载

更多资源
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文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册