黑马程序员——反射

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

反射: 
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

总结:就是把java类中各种成分映射成相应的java类

1、class 是关键字,用在类上,例如:class A{ } 
2、Class 是一个类,java程序中的类的类型就是Class(就像int是一个整数类型一样) 
3、Class 获取的是类上的属性和方法,不会获取类上属性的值, 
4、Class 不是对应用这个类声明的某一个对象,而是对应这个类

获取Class的方法:

    publicstatic void getClassDemo() throws ClassNotFoundException {

       String s = "abcdefg";

       "//通过对象的getClass()方法获取字类型的字节码文件"

       Class c1 = s.getClass();

       "//通过类型获取字节码文件"

       Class c2 = String.class;

       "/*通过Class.forName()获取字节码文件,若字节码没有加载进内存,就把文件加载进内存,若已经在内存中

       则直接取出字节码文件使用,内部是字符串,并且类所在的包也要写上*/"

       Class c3 = Class.forName("java.lang.String");

       System.out.println(c1 == c2);"//true"

       System.out.println(c1 == c3);"//true"

       System.out.println(c3 == c2);"//true"

       System.out.println(c1.getName());"获取类的名称,包括包名"

       System.out.println(c1.getSuperclass());"直接获取到Object的类,不论它上面有其他什么父类"

       System.out.println(c1.getModifiers());"最后修改时间"

       System.out.println(c1.getPackage());"获取包名"

       System.out.println(c1.getMethods());"获取所有方法,返回Methods[],不包括私有方法"

       System.out.println(c1.getMethod("charAt", int.class));"获取其中一个方法,指定方法名称,指定方法中参数类型的字节码文件"

       System.out.println(c1.getFields());"获取所有属性,返回Filed[]"

       System.out.println(c1.getField("name"));"获取指定属性,并返回Field"

       System.out.println(c1.isPrimitive());"判断是不是基本数据类型"

       System.out.println(int.class == Integer.class);"false"

       System.out.println(int.class == Integer.TYPE);"true"

       System.out.println(c1.isArray());"判断是不是数组类型"

    }

 

有9个预定义的Class对象: 
byte ,short,int,long,boolean,char,float,double,void

通过反射获取构造方法,并创建对象:

    publicstatic void getConstruct() throws ClassNotFoundException,

           InstantiationException, IllegalAccessException, NoSuchMethodException,

           SecurityException, IllegalArgumentException, InvocationTargetException {

       "//一般创建空参数的对象和有参数的对象"

       String str = "abc";

       String str2 = new String(new StringBuffer("abc"));

       "/**

        * 反射创建对象

        */

       // 获取没有参数的构造方法,并创建对象,然后对对象进行强转"

       Class c1 = Class.forName("java.lang.String");

       String s = (String) c1.newInstance();

 

       "// 获取有参数的构造方法,并创建对象"

       Class c2 = Class.forName("java.lang.String");

       "// 指定构造方法参数的字节码文件,可以通过参数的不同获取不同的构造方法"

       Constructor<String> con =c2.getConstructor(StringBuffer.class);

       "// 创建对象,并传入参数"

       StringBuffer sb = new StringBuffer("abc");

       String s1 = (String) con.newInstance(sb);

       System.out.println(s.getClass() == s1.getClass());"// true是同一个字节码文件"

       System.out.println(s == s1);"// false不是一个对象"

    }

 

通过反射获取类中属性: 
对应的类:Field Field[]

    publicstatic void getField() throws ClassNotFoundException, NoSuchFieldException,

           SecurityException,IllegalArgumentException, IllegalAccessException {

 

       Persion p = new Persion(10, "lisi");

       Class c = Class.forName("Persion.Persion");

       "// 获取的是Persion中num这个属性,不会获取他的值"

       Field f1 = c.getField("num");

        "/**

        * 这里获取的是这个Persion类中num属性,而不是Persion对应的具体的某个对象中的num

        * 不同对象他们对应的值不同,所以获取值的时候要传入对象,表示要获取那个对象这个属性的值

        */"

       System.out.println(f1.getInt(p));

       "// 修改某一个对象这个属性的值"

       f1.setInt(p, 30);

       System.out.println(f1.getInt(p));

 

       "// 获取所有的非私有属性,并返回Fiel[]"

       Field[] f2 = c.getFields();

       for (Field f : f2) {

           System.out.println(f.getName());

       }

       "/**

        * 获取所有属性,包括私有属性,并返回Fiel[]

        * c.getDeclaredFields();只是获取所有属性,但是并不能对私有属性进行操作

        */"

       Field[] f3 = c.getDeclaredFields();

       for (Field f : f3) {

           "//f.setAccessible(true);允许对某一个私有属性进行操作,"

           f.setAccessible(true);

           "//获取属性名称"

           System.out.println(f.getName());

       }

    }

 

用反射获取类中的方法: 
Method Methos[]

public static void getMethos() throwsClassNotFoundException, NoSuchMethodException,

            SecurityException,IllegalAccessException, IllegalArgumentException,

           InvocationTargetException {

       Persion p = new Persion(30, "lisi");

       Class c = Class.forName("Persion.Persion");

 

       "// 获取方法,传入要获取的方法名,方法中要传入的参数类型 的字节码文件"

       Method m1 = c.getMethod("setName", String.class);

       "// p这个对象调用SetName这个方法,传入的参数是“张三”"

       m1.invoke(p, new Object[] { "zhangsan" });"// =p.setName("zhangsan");"

       "// p这个对象调用getName这个方法,传入的参数是null,不需要参数"

       Method m2 = c.getMethod("getName", null);

       System.out.println(m2.invoke(p, null));"// = p.getName();"

       "//当一个方法是静态方法的时候使用m.invoke(null,'a'),不许要传入对象,因为静态方法不需要对象就能直接调用"

 

       "/**

        * 获取所有的方法,除了私有方法

        */"

       Method[] m3 = c.getMethods();

       for (Method m : m3) {

           System.out.println(m.getName());

       }

       "/**

        * 获取所有的方法,包括获取私有方法

        * c.getDeclaredMethods();获取但不能操作

        * m.setAccessible(true);允许操作

        */"

       Method[] m4 = c.getDeclaredMethods();

       for (Method m : m4) {

           m.setAccessible(true);

           System.out.println(m.getName());

       }

 

       "/**

        * 当方法中要传入的参数是数组时,如何传入参数

        * 参数类型是数组时候,一般我们会传入:m5.invoke(p,new String[] { "1", "2", "3","4" });

        * java 1.5之前传入的参数是数组类型,也就是把多个参数都封装到一个数组中传入,数组类型是Object[]类型

        * 所以new String[]数组Java虚拟机会直接看成new Object[],这样他会进行对数组进行拆开,然后把里面的元素作为参数传入

        * 而java1.5之后可以直接书写多参数,不用封装成new Object[],但是为了兼容1.5之前的版本,当传入的参数是数组类型的时候,会转换成Object[]类型(基本数据类型不能转换成Object[]类型),然后对数组进行拆开,然后把里面的元素当做参数传入,造成错误

        * 解决方式:

        * 1、 (Object) new String[] { "1", "2", "3","4" }强转

        * 2、new Object[] { new String[] { "1", "2", "3","4" } }

         * 把new String[]作为参数传入,这样就算拆开数组也不会有问题

        * 参数是String[] 要传入String[].class,不能传String

        * 参数是String 要传入String.class

        */"

 

       Method m5 = c.getMethod("shuzu", String[].class);

       m5.invoke(p, new Object[] { new String[] { "1", "2","3", "4" } });

    }

    "/**

        * 数组的反射

        * 具有相同的维度和元素类型相同的数组就是同一种类型,他们的字节码文件相同,Class对象相同

        */"

       int[] a1 = new int[] { 1 };

       int[] a2 = new int[2];

       int[][] a3 = new int[1][];

       String[] a4 = new String[] { "1", "2", "3","4" };

       System.out.println(a1.getClass() == a2.getClass());"// true"

       System.out.println(a1.getClass()==a3.getClass());"//false"

       System.out.println(a1.getClass() == a4.getClass());"//false"

       Object obj1 = a1;

       Object obj2 = a3;

       Object obj3 = a4;

       "// Object[] obj4 = a1;//基本数据类型数据不能用Object[]表示"

       Object[] obj5 = a3;

       Object[] obj6 = a4;

 

       "/**

        * 实例:

        * Arrays.aList();

        * 在java1.5之前参数是new Object[]

        * 在java1.5之后参数是T...a

        */"

       System.out.println(Arrays.asList(a1));"// [[I@1acd47]"

    "//在反射中,当获取的对象是一个数组时候,可以使用Array(不是Arrays),来操作数组"

       Class cla = a4.getClass();

       if (cla.isArray()) {

            int len = Array.getLength(a4);

           System.out.println(Array.get(a4, 2));

       }

 

内存泄露: 
当一个对象没有被继续使用,但是也无法被回收,造成内存浪费,就是内存泄露
 
实例:

    "/**

    * HashSet中是根据元素的hashCode()和equals()方法来判断元素是否相同

    * add()contains()和remove()方法要判断元素是否相同

     *在这里重写了Persion的hashCode()方法,根据num的值来判断

    * 当元素的值被修改后,他的hashco()的值不一样,hashset认为他们不是一个元素

    * 不进行删除,但是这个对象还存在集合中无法被使用,此时占用内存

    * 当这样的数据非常多以后就会造成内存问题

    */"

    publicstatic void memoryDemo() {

       HashSet<Persion> set = new HashSet<Persion>();

       Persion p = new Persion(10, "lisi", 100);

       set.add(p);

       System.out.println(set.size());"//1"

       "//修改num的值,导致hashcode()的值不相同"

       p.num = 0;

       set.remove(p);

       System.out.println(set.size());"//1"

    }

    publicclass Persion {

    privateint age = 3;

    privateString name;

    publicint num = 4;

    publicPersion(int age, String name, int num) {

       super();

       this.age = age;

       this.name = name;

       this.num = num;

    }

 

    @Override

    publicint hashCode() {

       "//使用num的值来判断是不是同一个元素"

       return num;

    }

}

 

"  /**

    * 反射实例

    */"

    publicstatic void demo() {

       "// 创建Properties 对象"

       Properties p = new Properties();

       "// 声明FileInputStream对象"

       FileInputStream fis = null;

       try {

           "//读取properties文件"

           fis = new FileInputStream("c://demo//a.txt");

           "//加载数据"

           p.load(fis);

           System.out.println(p.getProperty("demo") + "   " + p.getProperty("http"));

           "//获取demo多对应的值,然后创建他类的对象"

           Class c1 = Class.forName(p.getProperty("demo"));

           System.out.println(c1.getName());

           "//创建这个类的对象,这里使用的接口的类,因为传入的类实现了这个接口,就是这个接口的子类,多态的应用,提高扩展性"

           Rule r = (Rule) c1.newInstance();

           "//获取指定的方法,传入参数类型的字节码文件"

           Method m = c1.getMethod("down", String[].class, int.class);

           "//调用类中方法"

           m.invoke(r, new Object[] { new String[] { p.getProperty("http")}, 1 });

 

       } catch (Exception e) {

           e.printStackTrace();

       } finally {

           if (fis != null) {

                try {

                    fis.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

           }

       }

 

    }

"//定义接口,其他类实现这个接口"

package Persion;

 

public interface Rule {

    publicabstract void down(String[] s, int a);

}

 

"自定义类实现Rule 这个接口,利用传入的参数进行操作,可以利用传入的参数做任何操作,这里通过传入的参数获取网络资源,然后复制到指定位置"

 

public class Down implements Rule {

 

    @Override

    publicvoid down(String[] s, int a) {

       FileOutputStream fos = null;

       HttpURLConnection conn = null;

       try {

 

           URL url = new URL(s[0]);

           conn = (HttpURLConnection) url.openConnection();

           conn.setRequestMethod("GET");

           conn.setReadTimeout(3000);

           conn.connect();

           "把.之后的数据截取出来"

           String regex = "\\.\\w+";

           "//创建pattern对象,关联正则表达式"

           Pattern p = Pattern.compile(regex);

           "//通过pattern对象和要匹配的字符串关联,返回匹配引擎"

           Matcher m = p.matcher(s[0]);

           String name = null;

           "//不断循环找数据"

           while (m.find()) {

                name = m.group();

           }

           fos = new FileOutputStream("c://demo//a" + name);

           InputStream in = conn.getInputStream();

           int len = 0;

           byte[] by = new byte[1024];

           while ((len = in.read(by)) != -1){

                fos.write(by, 0, len);

                fos.flush();

           }

           System.out.println("OK");

 

       } catch (MalformedURLException e) {

           e.printStackTrace();

       } catch (IOException e) {

           e.printStackTrace();

       } finally {

 

           if (fos != null) {

 

                try {

                    fos.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

           }

           if (conn != null) {

                conn.disconnect();

           }

       }

    }

}

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

 


源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
### TCP传输原理与实现 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。其核心原理是通过建立端到端的连接,确保数据在不可靠的网络中能够可靠地传输。TCP 使用确认机制、流量控制、拥塞控制等机制来保障数据的完整性和有序性。 在 Java 中,TCP 通信可以通过 `Socket` 和 `ServerSocket` 类实现。客户端使用 `Socket` 连接到服务器,服务器端使用 `ServerSocket` 监听连接请求。通信过程中,数据通过输入流和输出流进行传输。 #### 客户端实现 客户端的主要任务是与服务器建立连接,并通过输出流向服务器发送数据,同时可以通过输入流接收服务器的响应。例如: ```java Socket s = new Socket(InetAddress.getLocalHost(), 10004); OutputStream out = s.getOutputStream(); out.write("Hello TCPClient".getBytes()); InputStream is = s.getInputStream(); byte[] buffer = new byte[1024]; int len = is.read(buffer); System.out.println(new String(buffer, 0, len)); s.close(); ``` 该代码实现了客户端与服务器的连接,并发送了一条文本消息,同时接收服务器的响应[^1]。 #### 服务端实现 服务端通过 `ServerSocket` 监听指定端口,等待客户端连接。一旦连接建立,服务端通过输入流接收客户端发送的数据,并通过输出流向客户端发送响应。例如: ```java ServerSocket ss = new ServerSocket(10012); Socket s = ss.accept(); InputStream in = s.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println(new String(buffer, 0, len)); PrintWriter out = new PrintWriter(s.getOutputStream(), true); out.println("<font color='red' size=7>客户端s你好</font>"); s.close(); ss.close(); ``` 该代码展示了如何在服务端接收客户端发送的数据,并向客户端发送 HTML 格式的响应[^3]。 #### TCP连接的建立与释放 TCP 连接的建立采用三次握手(Three-way Handshake): 1. 客户端发送 SYN(同步)报文给服务器,表示请求建立连接。 2. 服务器收到 SYN 报文后,发送 SYN-ACK(同步-确认)报文作为响应。 3. 客户端收到 SYN-ACK 后,发送 ACK(确认)报文,连接建立。 连接的释放采用四次挥手(Four-way Handshake): 1. 客户端发送 FIN(结束)报文,表示数据发送完成。 2. 服务器发送 ACK 报文,确认收到 FIN。 3. 服务器发送 FIN 报文,表示数据发送完成。 4. 客户端发送 ACK 报文,连接关闭。 #### TCP的可靠性机制 TCP 通过以下机制确保数据的可靠传输: - **确认机制**:接收方收到数据后,向发送方发送确认信息。 - **重传机制**:如果发送方未收到确认信息,则重传数据。 - **流量控制**:通过滑动窗口机制,控制发送速率,避免接收方缓冲区溢出。 - **拥塞控制**:通过慢启动、拥塞避免等算法,防止网络拥塞。 #### TCP的编程模型 TCP 编程模型通常包括以下几个步骤: 1. **创建 Socket**:客户端创建 `Socket` 对象,连接服务器;服务端创建 `ServerSocket` 对象,监听端口。 2. **获取流对象**:获取 `Socket` 的输入流和输出流,用于数据传输。 3. **数据读写**:通过输入流读取数据,通过输出流写入数据。 4. **关闭连接**:通信结束后,关闭 `Socket` 和流对象。 ### 示例代码:完整的 TCP 通信 以下是一个完整的 TCP 通信示例,包含客户端和服务端的代码。 #### 客户端代码 ```java import java.io.*; import java.net.*; public class TcpClient { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 8888); OutputStream out = socket.getOutputStream(); out.write("Hello Server!".getBytes()); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Server response: " + new String(buffer, 0, len)); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 服务端代码 ```java import java.io.*; import java.net.*; public class TcpServer { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server is listening on port 8888..."); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Client message: " + new String(buffer, 0, len)); OutputStream out = socket.getOutputStream(); out.write("Hello Client!".getBytes()); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值