黑马程序员——2010年java高新技术

本文深入探讨了Java编程中的高级特性,包括泛型、注解、反射、代理等核心概念及其在实际开发中的应用。从静态导入、装拆箱、可变参数、枚举、for循环增强等方面入手,全面解析Java技术细节,旨在帮助开发者提升编程能力并解决复杂问题。

                             ---------- android培训java培训、java学习型技术博客、期待与您交流! ----------
 

 

1import static语句导入一个类中的某个静态方法或所有静态方法。

举例:import static java.lang.Math.sin;

2、可变参数:方法接收的参数个数不定

int add(int ...args):在方法内部可以把args当做数组操作

3For增强语法:

for ( type 变量名:集合变量名 )  { … } 

注意事项:

迭代变量必须在( )中定义!

集合变量可以是数组或实现了Iterable接口的集合类

4、自动装箱:Integer num = 12;

5、自动拆箱:System.out.println(num + 12)

基本数据类型中还涉及了对象缓存:-128~127(一个字节大小),创建一个对象之后会缓存到一个池里,称为享元模式

6、枚举是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。当枚举中只有一个元素时,可以作为一种单例的实现方式。

【代码】

public class EnumTest {

public static void main(String[] args) {

//枚举基础使用

WeekDay weekday = WeekDay.FRI;

System.out.println(weekday);//打印FRI,为我们实现了toString方法

System.out.println(weekday.name());//返回字符串

System.out.println(weekday.ordinal());//获取索引,从0开始

//将字符串变成WeekDay对象

System.out.println(WeekDay.valueOf("SUN").toString());

//变成数组,获取长度

System.out.println(WeekDay.values().length);

}

//带抽象方法的枚举类

public enum TrafficLamp{

RED(30){

public TrafficLamp nextLamp(){

return GREEN;

}

},

GREEN(45){

public TrafficLamp nextLamp(){

return YELLOW;

}

},

YELLOW(5){

public TrafficLamp nextLamp(){

return RED;

}

};

//下一个灯,抽象方法,由每个匿名对象实现

public abstract TrafficLamp nextLamp();

private int time;//灯亮时长

private TrafficLamp(int time){

this.time=time;

}

}

//定义一个枚举

public enum WeekDay{

SUN(1),MON(),TUE(),WED,THI,FRI,SAT;

private WeekDay(){//默认调用无参构造

System.out.println("one");

}

private WeekDay(int day){

System.out.println("two");

}

}

}

7、反射:Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class

Class用来描述众多的java类。它的各个实例对象是类的字节码。得到字节码有三种方法。

(1)对象.getClass()

(2)类名.Class

(3)Class.forName(java.lang.String);

虚拟机缓存有字节码,就返回,没有的话就是用类加载器加载,并缓存在java虚拟机里,以便以后使用

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,如int[]  void

反射就是把Java类中的各种成分映射成相应的java类。

反射会导致程序性能下降

(1)变量对应Filed类:

//----------反射之--字段------------

ReflectPoint pt1 = new ReflectPoint(3,5);

ReflectPoint pt2 = new ReflectPoint(6,10);

//获取字节码上的变量Y。fieldY只代表字段,具体的值在不同的对象上都不同

Field fieldY = pt1.getClass().getField("y");

System.out.println(fieldY.get(pt1));

System.out.println(fieldY.get(pt2));

//private字段

Field fieldX = pt1.getClass().getDeclaredField("x");

fieldX.setAccessible(true);//暴力访问

System.out.println(fieldX.get(pt1));

System.out.println(fieldX.get(pt2));

//一定要会这个程序a改为bobj中有String变量

private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {

Field[] fields = obj.getClass().getDeclaredFields();

for(Field field : fields){

//字节码才一份,用==,比较符合

//字段的类型是什么

if(field.getType()==String.class){

String oldValue = (String)field.get(obj);

String newValue = oldValue.replace('b''a');

//重新设置值

field.set(obj, newValue);

}

}

}

(2)方法对应Method类:

Method methodCharAt = str1.getClass().getMethod("charAt"int.class);

//调用字节码的charAt方法,使用哪个对象啊

char ch = (Character)methodCharAt.invoke(str1, 1);

System.out.println(ch);

(3)构造方法对应Constructor:提供了一个newInstance方法创建对象,参数类型要与获得Constructor时的参数一致。

Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

String str2 = (String)constructor1.newInstance(new StringBuffer("abcd"));

(4)数组的反射作用:

int[] arr = {1,2,3,4,5};

printObject(arr);

private static void printObject(Object obj) {

Class clazz = obj.getClass();

if (clazz.isArray()) {

//获得哪个数组的长度啊

int len = Array.getLength(obj);

for (int i=0;i<len;i++) {

System.out.println(Array.get(obj, i));

}

else {

System.out.println(obj);

}

}

反射主要是实现框架功能:在编写框架时,要调用用户提供的类,但是不知道类叫什么,只能通过用户传进来的参数实例化对象。

8、内省操作:它主要用于对JavaBean进行操作,JavaBean是一种特殊的Java类,其中的某些方法符合某种命名规则,如果一个Java类中的一些方法符合某种命名规则,则可以把它当作JavaBean来使用。也了解了java7Map的新特性。

ReflectPoint pt = new ReflectPoint(3,5);

//如果当做普通类来操作,很麻烦

String propertyName = "x";

//"x"-->"X"-->getX()-->methodGetX-->invoke

//属性扫描,PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。 

PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt.getClass());

//得到x属性的读方法

Method methodGetX = pd.getReadMethod();

//调用读方法

System.out.println(methodGetX.invoke(pt));

//获取写方法,更改x的值

Method methodSetX = pd.getWriteMethod();

methodSetX.invoke(pt, 30);

//调用读方法

System.out.println(methodGetX.invoke(pt));

 9注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac 编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

//注解可作用在哪里

@Target(ElementType.TYPE)

//注解保存到那个步骤

@Retention(RetentionPolicy.RUNTIME)

public @interface ItcastAnnotation {

String value();//添加字符串属性

int[] arrayattr();//添加数组属性

}

//当只有一个value属性时,可以不用写value=

@ItcastAnnotation(value="xyz",arrayattr={1,2,3}/*2*/,lamp=TrafficLamp.GREEN,annotationAttr=@MetaAnnotation("yyy"))

public class AnnotationTest {

public static void main(String[] args) {

Class clz = AnnotationTest.class;

Class itcastClz = ItcastAnnotation.class;

//ItcastAnnotation在不在啊

if (clz.isAnnotationPresent(itcastClz)) {

//获得Annotation

ItcastAnnotation annotation = (ItcastAnnotation)clz.getAnnotation(itcastClz);

System.out.println(annotation);

//打印字符串属性

System.out.println(annotation.value());

//打印数组属性

for(int i : annotation.arrayattr()){

System.out.println(i);

}

}

}

}

 10泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

【基本应用】

public class GenericTest {

public static void main(String[] args) throws Exception {

//表名ArrayList只能存String

ArrayList<String> list = new ArrayList<String>();

list.add("java01");

list.add("java02");

//取的话,是String类型的

String str = list.get(1);

System.out.println(str);

//表名构造函数时String类的,在newInstance时就不用强制类型转换了

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

String str1 = c.newInstance(new StringBuffer("abc"));

System.out.println(str1.charAt(1));

}

}

    泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型信息”,使程序运行效率不受影响。对于参数卷的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中添加其他类型的数据。如利用反射。

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:

    (1)整个称为ArrayList<E>泛型类型

(2)ArrayList<E>中的E称为类型变量或类型参数

(3)整个ArrayList<Integer>称为参数化的类型

(4)ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数

(5)ArrayList<Integer>中的<>念着typeof

(6)ArrayList称为原始类型

    参数化类型与原始类型的兼容性:

    (1)参数化类型可以引用一个原始类型的对象,编译报告警告,例如,
    (2)Collection<String> c = new Vector();//可不可以,不就是编译器一句话的事吗?

(3)原始类型可以引用一个参数化类型的对象,编译报告警告,例如,
    (4)Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去

【实验】

    Vector<String> v = new Vector();

Vector v1 = new Vector<String>();

    添加元素时,add方法参数类型和get方法的返回类型看左侧

    参数化类型不考虑类型参数的继承关系

    (1)Vector<String> v = new Vector<Object>(); //错误!///不写<Object>没错,写了就是明知故犯

    (2)Vector<Object> v = new Vector<String>(); //也错误!左边明确说可以装所有类型,但是右边只装了String,矛盾了

    编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

  Vector<Integer> vectorList[] = new Vector<Integer>[10];

    泛型中的?通配符

    使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

限定通配符的上边界:

正确:Vector<? extends Number> x = new Vector<Integer>();

        是Number的子类,最高是Number

错误:Vector<? extends Number> x = new Vector<String>();

    限定通配符的下边界:

正确:Vector<? super Integer> x = new Vector<Number>();

    Integer的父类,最低是Integer

    错误:Vector<? super Integer> x = new Vector<Byte>();

    泛型综合应用案例

    HashMap<String,Integer> map = new HashMap<String,Integer>();

    map.put("01", 10);

    map.put("02", 20);

    map.put("03", 30);

    //Set里面装的是Map.Entry,Entry里面装的是<String, Integer>

    Set<Map.Entry<String, Integer>> entrySet = map.entrySet();

    //遍历

    for(Map.Entry<String, Integer> entry : entrySet){  System.out.println(entry.getKey()+"="+entry.getValue());

    }

 

11、类加载器:
    (1)Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
    (2)类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是不是java类,这正是BootStrap。
    (3)Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载

 

12、代理:
动态代理技术:
1.JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
2.JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。


代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中


public class MyProxy {
 private Person p = new Zhangsan();
 //Demo---- 

Person person = MyProxy.createProxy();   person.sing(”爱你爱你“)  person.dance();
 public Person createProxy(){
 
  return (Person) Proxy.newProxyInstance(MyProxy.class.getClassLoader(), p.getClass().getInterfaces(),new InvocationHandler(){

   /*
   * proxy:把代理对象自身传递进来
   * method:代表当前调用的方法
   * args:调用方法的参数
   */
   public Object invoke(Object proxy, Method method, Object[] args)
     throws Throwable {
    String methodname = method.getName();
    if(methodname.equals("sing")){
     System.out.println("吃饭啦!!");
     return method.invoke(p, args);
    }else if(methodname.equals("dance")){
     System.out.println("睡觉啦!!");
     return method.invoke(p, args);
    }else{
     System.out.println("呀呀呀 不做啦");   
    }
    return null;
   }
  
  });
 }
 
}

 

个人总结:

     主要学习了静态导入,装拆箱,可变参数,枚举,for循环增强,反射,泛型,注解,代理等知识,内容很多,如果简单的使用,很容易上手,但是认真学习他们的细节,就没那么容易。掌握了这些细节,对于我们开发,阅读其他的程序都是非常有帮助的。

                             ----------android培训java培训、java学习型技术博客、期待与您交流! ----------


                                                         详细请查看:http://edu.youkuaiyun.com/heima

### 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(); } } } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值