findViewById如果找不到控件

这不是什么高级的话题, 只是写在这里提醒初学者们, 不要犯这样的错误… 如果你的findViewById找不到想要的控件, 但是该控件的id等配置都没有任何错误, 那么请看看获取控件的语句, 是不是写在了 setContentView(R.layout.activity_reminder_edit); 这句话的前面… 在没有setContentView的情况下, 直接通过 来获取控件, 那么就这么悲剧了… 一串的null, 接下来就准备接收空指针错误吧!

Android4.0以上版本OptionsMenu无法显示图标的问题

今天在写一个OptionsMenu的时候,虽然在xml文件当中加入了icon属性,但是那个图标弄死就是显示不出来。 情况是这样的,这是我配置的list_menu.xml: 就拿这一个菜单项目为例, icon属性设置了一个ic_menu_add, 下面看这段正常不过的java代码: 代码就不解释了, 很开心部署到手机, 点Menu按钮之后整个人都不好了, 没有ICON. 翻墙出去找google帮忙. 以下解决办法, 改编自http://stackoverflow.com/questions/19750635/icon-in-menu-not-showing-in-android, 多谢外国猿~ 谷歌的高大尚你不懂的, 他硬生生就不让你在Menu里面显示图标. 据说(没有去深究这个啦)谷歌在4.0以后, 将menu中的setOptionalIconsVisible这个方法, 变成了私有的… 并且默认值为false. 你懂的… 这意味着设置一百遍icon都是徒劳… 这时想起了张孝祥老师讲过的一个关于反射的故事… 既然知道有这么一个私有的方法可以设置icon的显示状态, 就暴力解决问题吧~ 反射得到menu的setOptionalIconsVisible方法, 然后呵呵 搞了这个一个方法, 然后在onCreateOptionsMenu里面一调, 整个人就好了~

Android Studio写测试类技能get

终于开始android的学习,学习阶段,真的没有太多时间来写博客;不过时间就像XX,挤一挤总有的,这不就挤出来了…以前用eclipse写过一些android程序,现在Android Studio出来了,二话不说直接上手。关于Studio的设置就不说了,度娘告诉你。立志做”爱美”的程序员,所以我的的IDE环境一般都是这样 或者这样 不要误会,直男一枚,只是觉得猿类的世界,也可以是多彩的,用颜色告诉自己,猿的世界,有无限种可能,想象无界,创造无界。 进入今天的主题,就是Studio中写测试类。进入了Studio,省了好多事情啊,就不用在Manifest中添加什么library啊instrumentation了,直接搞起来! 每当在Studio中创建新的工程,在java文件夹中,都会有一个和你创建的包名一模一样的androidTest包。我们的测试类就是在这个包里面写啦! 来到这个包下,创建一个类,这个类中写了一个需要测试的方法 MyClass 这个add()方法就是需要测试的方法。接下来就可以创建测试类啦! TestClass 测试类必须继承TestCase或者其子类AndroidTestCase、InstrumentationTestCase,不然没办法工作啊!另外,测试类中的方法,必须以小写的test开头,切记~大功告成,最后就是右键你的TestClass类,运行就可以了。但是Run会有三个选项,就像这样 看图说话,选那个有小机器人图标的TestClass喔!Android中的JUnit,还是要把这个测试类部署到手机上的喔,其他两个方法,貌似不好用的哈。 点击TestClass后,就会跳出来AVD的选择对话框了,就像这样 直接OK;然后,只要测试通过,那就是这样的一番情景了 绿色,恭喜你!测试成功! 对于初学者来说,省掉了在Manifest中加入library和instrumentation的麻烦。不过初学者,还是多配配环境,多了解原理的好!关于JUnit,其实还有好多深奥的东西需要研究,精力有限,待我练完Android宝典,再续JUnit~ Studio测试类,一起分享~

XML解析-学习Pull和DOM4J的使用

很久没有写博客了,我认为黑马最最可贵的地方在于培养一个开发人员写博客的习惯。在写博客的过程当中,可以巩固以前的旧知识,同时增加了发现新问题的几率,对于提高自己是一个很好的途径。废话不多说,就将XML的两个常用解析器拿来记录一下。 一、Pull、DOM4J解析器概述 在概述部分,我都将这两个解析器按照自己的理解来阐述一下。自己是菜鸟,就不要写出高大上的话,这样才能真正把知识转化为自己的。 1.Pull解析器 Pull解析器是Android内置的XML解析器。Pull的内部,实现的是基于事件驱动的SAX解析思想,一次读取一行XML文件,并加载一行,解析一行。Pull的有点在于其可以控制SAX读取指针的动作,程序让它往下走,指针才会读取下一行。 2.DOM4J DOM4J是开发JDOM的意外产物。据说开发JDOM的一帮子人内讧,一帮说要这样,一帮说要那样,然后分家。分家出去的那帮人做了DOM4J,又据说性能等各方面完暴JDOM,成了现在最流行的XML解析器。书写简单,效率高,集合了SAX和DOM思想,怎一个“屌”字了得~ 二、两种解析器的应用 1.Pull解析器使用步骤 使用Pull解析XML文件的大致步骤如下: 第一步:创建一个解析器工厂 第二步:通过解析器工厂,获取一个解析器对象 第三步:为解析器设置一个输入流,关联需要解析的XML文件 假设这个需要解析的就是这个student.xml文件,并指定解析使用的字符编码是utf-8格式。 第四步:获取解析器事件类型,可以根据事件类型来执行相对应的操作 事件类型是一个整型数据,代表着解析器类当中的诸如START_DOCUMENT的一系列常量。 下面的例子,就是解析一个student.xml文件,并将文件中的每个元素,都封装成Student对象,存放入List集合中,这个例子的关键点在于分清楚每一个事件类型应该采取什么样的操作。 先来看看这个XML文件: number、name、age、sex、score这些元素,应该被封装成一个Student类,这个Student类如下: 写好了Student类,下面要做的就是解析XML文件。解析的整体思路就是利用Pull解析器的getEventType()方法,获取解析器当前的标签状态,判断该标签是起始标签还是结束标签,做出相应的动作。如果是起始标签,又可以使用解析器的getName()方法获取标签名,通过判断标签名,再进行进一步的操作。代码中有详细的注释。 示例代码: 程序输出结果: 解析并封装成功~ 除了解析,Pull也提供了写如一个XML文件的方法,通过XmlSerializer对象的一系列方法(序列化)实现。写入的方式相对简单,就是调用startDocument(),startTag(),text()等方法,创建标签即文本内容即可。下面的代码将创建一个名为stu.xml文件。 示例代码: 生成的stu.xml文档: 2.DOM4J解析器使用步骤 老大哥来了,使用起来真的是方便。DOM4J集合了SAX和DOM的思想,在关联解析文件的时候,用的是SAXReader对象,而对XML进行增删改查的过程,用的又是DOM的思想。不愧是解析思想的集大成者。废话不多说,用代码说明一下DOM4J的使用,真的是简单~ 2.1DOM4J解析XML文件的步骤 第一步:创建SAXReader对象 第二步:关联解析文件,得到该文件的Document对象,这是DOM思想的开始 2.2DOM4J回写(这里对于回写就不做说明啦)的步骤 DOM4J的回写是通过XMLWriter对象,配合OutputFormat对象实现的,简单看一下吧,用起来很方便。 第一步:创建OutputFormat对象,这个对象是用于格式化输出的XML文件,通过两个静态方法createPrettyPrint()和createCompactFormat()来创建格式化的输出和紧凑的输出;格式化的就是我们一般看到的XML格式,compact的格式就是将XML文件输出在一行,供计算机阅读;这里我们就是用pretty格式啦! 第二步:创建XMLWriter对象,这个对象接收OutputStream和OutputFormat对象作为参数 第三步:回写修改之后的XML对象,这个XML对象现在是以Document的形式存在于内存,调用write方法将他写回到XML文件 第四步:由于XMLWriter要开流,所以要关闭资源 完成啦~ 下面就用具体的代码来阐述如何用DOM4J来对XML文件进行增删改查的操作。先来看看Student.xml这个需要被操作的文件。 Student.xml 由于大部分方法都要获取Document对象,也都要回写Document对象,所以先将这两个方法封装到一个工具类中,方便调用。 DOM4JUtils工具类 写好了工具类,就可以开始对XML文件进行解析了,下面的代码中运用了JUnit Test的方式对每一个方法进行测试,就不需要写一个main方法,省去了在main方法中一个一个调用的麻烦。 JUnit小技巧:在方法上面,加上@Test注解(下面有示例),然后在报错行按下Ctrl+1导入JUnit包,接着就可以双击方法名——>Run as——>JUnit Test即可运行该方法;如果看到下图的绿色条,就是方法运行成功,没有报错 三、小案例 这个案例实现了一个简易的商品管理系统,用户可以选择需要的操作,完成对商品XML文件的增删改查操作。有兴趣就看看吧,不想写注释了。。。有点累咯大家见谅~大致的实现思想就是基于DOM4J的解析和回写。当然了,第一次启动程序的时候,需要先添加一些列的商品,然后在进行其他操作。代码里没有很严谨,没有对输入做校验,所以才叫简易系统嘛哈哈,我就不为难自己了~ pro.xml ProductManagingSystem KEEP CALM AND CARRY…

JavaEnhance——类加载器

一、概述 1.类加载器的定义 所有Java类在使用的时候都必须通过类加载器加载到内存。Java虚拟机可以安装多个类加载器,系统默认的,有三个主要的类加载器:BootStrap, ExtClassLoader, AppClassLoader。它们分别负责加载特定位置的类。 2.类加载器的性质 类加载器也是Java类。因此,类加载器也要被一个类加载器加载,才能工作。这么说来,必须有一个不是Java类的类加载,才能完成上述工作。这个类加载器就是BootStrap,它是所有类加载器的父类。 3.类加载器的继承关系 Java虚拟机中的所有类加载器都具有其父子关系的树形结构,在实例化每个加载器的对象时,需要为其指定一个父级类加载器对象或者默认采用系统类加载器为其父级类加载器。 二、委托机制 在类加载器的委托机制中,子类类加载器都会先委托其父类类加载器去寻找要加载的类;如果父类加载器寻找到该类,就直接加载该类;如果没有找到,就会逐级返回,直到回到子类加载器,由子类类加载器加载该类。 三、自定义类加载器 自定义类加载器必须继承ClassLoader类,并复写findClass()方法。 提示:没有复写loadClass()方法的原因在于,loadClass()方法会找其父类加载器,如果父类加载器无法完成类的加载,loadClass()方法回返回来调用findClass()方法。如果复写loadClass()方法,那么去调用父类的实现还需要自己动手写,代码复杂。所以只需要复写findClass()方法即可。 下面的例子实现了用自定义类加载器加载一个类,并将这个类进行加密解密,也就是说,只有自定义类加载器才能调用该类。 需要被加密的类: 自定义类加载器: 类加载器测试类: 程序输出结果:Shit happens…

JavaEnhance——枚举、注解及泛型

枚举 一、概述 如果一个变量的取值要被限定在一定的范围内,例如星期的取值,限定在1~7的范围内,并且想要在编译期就能指出变量取值超出范围的错误,就可以使用枚举。枚举相当于一个类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。 二、枚举的应用 1.使用普通类模拟枚举 使用普通类模拟枚举的时候,首先将构造方法私有化,然后在类的内部创建常量,那么其他类在调用这个类的时候,只能得到模拟枚举类中的常量,不能new出新的值。 示例代码: 这样就实现了一个最基本的枚举类,除了类中定义的两个常量外,不可能再为weekDay赋另外的值。接下来,可以在模拟枚举类中加入方法。 示例代码: 这里只写了两个常量,如果有七个,那么这个nextDay()方法中的if else语句就会很长,为了避免长代码,可以将nextDay()定义为抽象方法,由每个子类对象去实现。 示例代码: 用抽象方法可以将大量的if else语句转换成由一个个独立的子类来实现该抽象方法,简化了代码。 2.定义枚举类在用普通类模拟了枚举类之后,现在定义一个真正的枚举类。在类中定义一个内部枚举类。 示例代码: 枚举类内部实现了toString()方法。下面为枚举类定义构造方法。 示例代码: 默认情况下,枚举的成员使用的都是无参构造方法。只要用到枚举类,里面的所有静态成员都会被初始化。如果指定要调用有参构造方法,只需在枚举成员后加上小括号,写入参数即可。 示例代码: 最最复杂的枚举,就是带有抽象方法的枚举,下面运用枚举实现一个交通灯系统。 示例代码: 三、枚举总结 1.枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后面要有分号与其他成员分隔。把枚举中的成员方法或变量等放在枚举元素的前面, 编译器会报错。 2.带构造方法的枚举 (1) 构造方法必须定义成私有(2) 如果有多个构造方法,在枚举元素后面加上小括号来调用指定的构造方法(3) 枚举元素MON和MON()的效果一样,都是调用默认的构造方法 3.带抽象方法的枚举 每个元素都是由枚举类的子类来生成的实例对象,这些子类可以采用类似内部类的方式来定义并实现枚举中的抽象方法。 4.枚举只有一个成员时,就可以作为一个单例的实现方式。 注解 一、概述 注解是JDK1.5开始的新特性,一个注解就是一个类,运用注解的时候就是创建了一个注解的实例对象。现行的框架,如Hibernate,Spring,EJB以及Struts2的一部分,都是基于注解技术。注解相当于一个标记,可以添加在包、类、字段、方法、方法的参数以及局部变量上。 二、常见注解 1.@SuppressWarnings该注解用于去除编译期出现的警告提示,如调用了过时方法时的警告提示 2.@Deprecated该注解用于标识一个方法等已经过时,不建议使用;添加了该注解的方法等,或被一根横线划过 3.@Override该注解用于标识一个方法是其父类中方法的复写;如果方法与父类中的方法不一致,会得到报错提示 三、元注解 元注解就是添加在注解类上的注解,用于标识该注解的生命周期以及可以添加的位置等。 1.@Retention @Retention注解有三个取值,分别对应着注解的生命周期,它们是:@RetentionPolicy.SOURCE,@RetentionPolicy.CLASS,@RetentionPolicy.RUNTIME;由于javac在编译源文件的时候或是classLoader将class文件加载到内存的过程中,会将一些注解去掉,会导致注解失效 2.@Target@Target元注解接收一个ElementType数组作为参数,指定某个注解类能被添加到哪些地方@Target({ElementType.METHOD, ElementType.TYPE})表示这个注解能被添加到方法和类上 四、注解的应用 1.创建自定义注解注解是一个类似接口的类,用@interface + 类名来表示。 示例代码: 将自定义注解类添加到一个类上 示例代码: 程序无打印结果,是因为自定义注解上没有添加标识该注解声明周期的元注解。 添加元注解:…

面试

模拟计算器: code 注释也不想写了,也不想给优化了,原生态代码,多年之后看看,会觉得当时好菜~ 复制文件夹(包括文件和文件夹中的文件夹) code

Java基础—反射机制

一、概述 反射是JDK1.2以来就有的特性。学习反射,首先要了解Class这个类, 1.Class类Java中的类描述一类事物的共性,该类事物有什么属性,没有什么属性。但是这个类不管这些属性的具体值,类只负责描述这些属性。属性的具体值,是由这个类的具体实例对象来确定的。这些类,也可以理解为Java中的同一类事物,而用来描述这些类的类,就是Class类。每一个Java类都会有类名,包名,成员变量,方法,父类等等,这些属性,都可以在Class类中获取。如何得到Class类的对象?首先,Class对象对应的是内存中的字节码文件。字节码文件是源代码编译好的class文件,当要使用某个类的对象时,要将class文件加载到内存,用这个字节码复制出一个一个对象。Java程序中用了几个类,就有几份字节码;这些字节码就是Class类的对象。 2.获取Class类的对象获取字节码对应的实例对象有三种方法: 1)类名.calss;如:System.class;2)对象.getClass();如:new Date().getClass();3)Class.forName(“类名”);如:Class.forName(“java.util.Date”); 扩展:Class.forName(“java.lang.String”);forName()方法可以返回指定类名的字节码。得到一个类的字节码有两种情况:1)这个类的字节码已经加载到内存,那么直接找到这个字节码,返回;2)这个类的字节码还没有在虚拟机里,那么用类加载器加载,然后缓冲起来,forName()方法返回这个字节码 3.九个预定于Class对象八个基本类型对应的Class对象,void也有对应的Class对象,即void.class。下面用一个示例来演示Class类。 示例代码: 注意:只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[],void… 二、反射 反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类用一个Class类的对象来表示;类中的组成部分,成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示。Field、Method、Constructor、Package等类,代表了一个Java类中的各个成分。如,Method代表了一个类中的所有方法;具体的方法1,对应的是Method这个类的实例对象methodObj1。 三、反射中的类 1.Constructor类代表一个类中的构造方法。 1)得到某个类所有的构造方法 2)得到某个单独的构造方法 3)创建实例对象 注意:-String类有很多的构造方法,那么单独获取一个构造方法,靠的就是指定这个构造方法中的参数;上面的例子,就是用了String类接收StringBuffer作为参数的构造方法; -JDK1.5之后出现了可变参数,getConstructor()方法接收的是可变参数列表,参数可以是一个,可以是多个;这些参数,都代表这String类当中的一个构造方法; -使用String的构造方法创建String对象的时候,调用constructor对象的newInstance()方法,传入一个StringBuffer作为参数,来构造一个string对象;根据上一条所说,编译时期不知道这个constructor对象代表的是哪个类的构造方法,只有到现在这个运行时才能明确;同时,newInstance方法返回值是Object类型,所以要加上一个String的类型转换 -得到构造方法的时候需要类型,调用这个构造方法的时候同样需要传递同样类型的对象 4)Class.newInstance()方法 注意:Class类中也有一个newInstance()方法;这个方法用于获取某个类的无参构造方法;这是为了提供简便;用反射机制创建一个类的对象要先获取这个类的Class对象;然后通过Class对象获取constructor对象;最后由constructor创建Object;如果可以省去中间步骤,直接由Class对象获取构造方法,可以提高一些效率;Class类的newInstance()方法中运用了缓存机制,将第一次获取的空参数构造方法缓存起来;如果下次还需要调用,就不需要获取,直接从缓存中调用,提高运行速度;也从侧面说明反射比较消耗性能 示例代码: 程序运行结果:abc 2.Field类Field类代表某个类中的一个成员变量 使用Field类获取类中的成员: 程序运行结果: 3.练习将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的”b”改成”a” 示例代码: 程序运行结果:aall:aasketaall:itheima 4.Method类Method类代表某个类中的一个成员方法 1)得到类中的某一个方法 2)调用方法 示例代码: 程序运行结果:2 注意:-如果invoke()方法的第一个参数为null,说名这个method对象对应的是一个静态方法,因为不需要对象进行调用 -JDK1.5的invoke()方法可以接收可变参数,在JDK1.4版本,invoke()方法的第二个参数只能接收一个Object类型的数组;不过JDK是向下兼容的,在JDK1.5以后使用数组参数也可以 5.用反射执行某个类中的main方法用反射的方式调用某个类的main方法,可以不用事先直到那个类的名称。这个类的名称,可以通过参数的方式传递给程序,然后在程序中,用反射的方法调用那个类的main方法。而传统方法调用一个类的main方法,必须事先知道那个类的名称,然后用静态调用的方式调用其main方法。 示例代码: 程序运行结果: 6.数组的反射每一个具有相同元素类型和维度的数组都属于同一个反射出来的Class。 示例代码: 注意:-基本数据类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本数据类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用;当一个基本数据类型的一维数组作为Object使用时,可以理解为所有的对象都是Object,基本数据类型的一维数组也不例外;但是当将一维数组转换为Object[]数组类型时,意味着一个数组里面装的是Object类型的对象;那么,String[]数组里面装的是String对象,可以是Object;int[][]二维数组里面装的是int[]对象,也可以是Object;但是int[]一维数组里面装的是int基本类型数据,不可以是Object;所以int[]不能被当成Object[]使用; -Arrays.asList()方法,在JDK1.5之前接收的是一个Object[]数组作为参数;那么根据上一条所说,当传入一个String[]数组的时候,满足String[]数组可以当成Object[]数组的条件,就将String[]数组中的值分别拿出来装进List,再打印出来;而将int[]基本数据类型的数组传入的时候,int[]数组不能被当成Object[]数组使用,那么就会回到JDK1.5版本使用更高级的处理方式,将int[]数组当成是一个整体元素,不会将里面的元素再取出,即List里面装了一个元素,就是这个int[]类型的数组,所以无法打印出数组内的元素 用反射获取数组中的元素数组有length属性,有索引下标,可以设置数组的值等,现在通过数组的反射来操作数组 示例代码: 程序运行结果: 四、ArrayList-HashSet的比较及HashCode分析 1.概述ArrayList是一种有顺序的集合,相当于一个数组。加入对象的时候,首先找到第一个空位,将对象的引用存储进来;第二个对象,就按顺序依次往后添加;当添加到相同对象的时候,就将相同的引用存储进来。ArrayList是按照先后顺序依次添加对象。 HashSet在存储的时候,首先会看集合中是否有相同的元素,如果有,就不会添加;如果要添加重复对象,一定要先删除原先的,再添加新的。 2.hashCode()方法的作用如果要查找一个集合中是否包含某个对象,通常的做法是从第一个元素开始,逐一取出每个元素和目标元素进行比较,如果有相同的,就返回真,如果没有则返回假。那么,当一个集合中有很多很多元素的时候,譬如一万个;现在假设这个集合中没有包含目标元素,如果要进行查找,还是要从第一个元素开始,取出比较一万次,没有找到匹配,返回假。这样的效率特别低。hashCode()方法可以避免这样的事情发生,提高程序效率。hashCode称为哈希值,是由哈希算法生成的一个值。哈希算法将集合分成若干个存储的区域,每个对象都可以计算出一个哈希值,将这个哈希值进行分组,每组分别对应某个存储区域,根据一个对象的哈希值就可以确定该对象存储在哪个区域。如图: HashSet采用哈希算法存取对象。它内部通过对某个数字n取余的方式来对哈希值进行分组和划分对象的存储区域。每个对象都有继承自Object类的hashCode()方法。当要从HashSet集合中查找某个对象时,Java先调用该对象的hashCode()方法获取其哈希值,然后根据哈希值找到相应的存储区域,最后取出该区域中的每个元素与该对象进行equals()方法的比较。这样就无须遍历整个集合,提升了检索性能。 高能:当一个已经存储进HashSet中,就不要修改这个对象存于hashCode运算的字段;因为一旦修改,该对象的哈希值就会改变,那么再去查找或者删除该对象的时候,都无法成功;这有可能造成内存泄漏的情况(Java中内存泄漏的线程) 五、框架的概念即用反射技术开发框架的原理…

Java基础—网络编程(二)

@[toc]网络编程(二) 一、TCP协议通信 1.上传图片练习1)将图片上传到服务器端保存。 示例代码: 程序运行结果:上传成功 2)TCP客户端并发上传图片这个服务端有局限性。当一个客户端连接服务器之后,因为服务器是单线程,那么其他客户端如果想连接服务器,只能带前一个客户完成所有任务,才能连接。要同时处理多个客户端请求,应该明确客户端要在服务器端要执行的代码,然后将每个客户端封装到一个线程当中,同步执行。 示例代码: 2.检测用户名练习客户端通过键盘录入用户名,如果该用户存在,在服务器端显示xxx,已登录;在客户端显示xxx,欢迎光临。如果用户不存在,在服务端显示xxx,尝试登录;在客户端显示xxx,该用户不存在。 示例代码: 3.自定义浏览器1)HTTP请求消息头请求头信息中包括了发送该请求的主机地址,端口,路径,可以接受的应用程序类型,所使用语言,封装压缩形式等信息。请求头信息示例如下: 模拟一个浏览器,想服务器发送请求头信息,获取页面。 示例代码: 二、URL类 1.概述URL(Uniform Resource Locator)类代表一个同一资源定位符。该类是指向互联网资源的指针。 2.常用方法-String getFile():获取此URL的文件名-String getHost():获取此URL的主机名-String getPath():获取此URL的路径部分-int getPort():获取此URL的端口号-String getProtocol():获取此URL的协议名称-String getQuery():获取此URL的查询部 3.常用方法演示 示例代码: 程序运行结果: 注意:没有指定端口,返回-1;开发时要进行判断,如果port的值为-1,要给port赋值为80 三、URLConnection类 1.概述URLConnection类对象是URL对象调用openConnect()方法之后的返回值,就能得到这个URL的连接对象,也就是目标主机对象;获取URLConnection对象可以方便获取Socket输入流对象。 2.URLConnection类演示 示例代码: 注意:url.openConnection().getInputStream()这行代码,可以简写成url.openStream();该方法是URLConnection类中获取InputStream的便捷方法 四、扩展知识 1.Socket空参数构造函数通过调用connect()方法连接主机;connect()方法可以接收一个SocketAddress对象作为参数;SocketAddress类的子类InetSocketAddress类封装IP地址和端口;那么以前在创建Socket对象的时候分开写主机IP和端口,现在也可以调用connect方法,传递一个InetSocketAddress对象即可。 2.ServerSocket类接收的backlog参数backlog表示队列的最大长度。它代表能同时连接到服务器的最大客户端个数。在服务器端开发时,要指定这个参数,避免服务器因连接数过多而死机。 五、域名解析 1.概述IP地址不容易记忆,通常人们在访问网站的时候,在地址栏输入的都是类似于www.baidu.com这样的域名。但是要访问到网络上对应这个域名的那个主机,需要将这个域名解析成IP地址。这个过程,需要DNS域名解析服务器来完成。DNS服务器中记录的是每个域名对应的IP地址映射表。 2.基本原理 PC在访问网站的时候,要走这4步流程。在浏览器输入域名之后,第1步,到本机C盘“(C:\windows\Systems\drivers\etc\)下的hosts文件,寻找这个域名是否在本地有已经配置的IP地址,如果有,直接访问该IP,否则,进入第2步;第2步,访问公网DNS服务器,找到DNS服务器上的域名——IP映射关系;第3步,DNS服务器将对应的IP地址返回给PC;第4步,PC端访问该IP地址,找到公网上的指定主机。 注意:127.0.0.1与localhost之间的映射关系在本机上C盘下的hosts文件中。该文件可以用于屏蔽恶意网站。

Java基础—网络编程(一)

网络编程(一) 一、网络模型 1.OSI参考模型OSI网络模型的每一层,都有自己特有的数据封装特征信息。两台主机通信,首先在应用层将数据封装。将会给数据加上应用层的特征信息,传递给OSI网络模型的下一层表示层;表示层也会给数据加上自己特有的特征;以此类推。到传输层(TCP/IP和UDP协议所在层),加上TCP的特征信息,交由网络层;网络层将IP协议赋给该数据包,标识该数据包的目的地,再交给数据链路层;数据链路层标识该数据包的传输方式,交给最后一层物理层(网线,光纤,无线设备);这时,数据封包结束,通过物理层传输到目的主机的物理层,由对方主机,从底层物理层开始,对数据进行数据拆包。 2.TCP/IP参考模型TCP/IP参考模型分为四个层次。它将OSI参考模型的应用层、表示层和会话层合并为应用层,保留了传输层和网际层,最后将数据链路层和物理层合并为主机至网络层。 注意:把用户应用程序最为最高层,把物理通信线路最为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准。网络模型的每个层次都有自己的传输协议。传输层的协议是TCP和UDP协议;网际层最常用的是IP协议;应用层通常使用HTTP/FTP协议 二、网络通信三要素 1.对方IP地址网络通信的首要素是要知道对方的IP地址,确定对方的主机在网络上的位置,才能发起进一步的请求。 2.应用端口网络通信第二要素是获取对方的端口。要将数据要发送到指定的应用程序上,就必须直到对方用于接收本方数据的应用服务端口。每个网络应用程序都有一个网络端口用于接收数据。主机上的端口可以在0-65535之间任取,但是0-1024默认作为系统端口,不建议使用。 3.通信协议通信协议,即通信规则。国际组织定义了一个在传输层和网络层通用的协议————TCP/IP协议。 三、IP地址 1.概述IP(Internet Protocol)协议是网际层的主要协议,支持网间互连的数据包通信。它提供无连接数据包传送,数据包路由选择和差错控制。IP地址分4段,每段为1个字节,每段最大值为255。IP地址用于确定主机在网络中的位置。 2、本地回环地址127.0.0.1是本地回环地址,可以用于测试网卡工作是否正常或这用于测试本地网页等。 3.局域网IP地址192.168开头的IP被保留,不用于公网,用于局域网。其中有一个例外,第四个字段为255的被保留作广播IP地址,给这个IP发送的消息,局域网内所有主机都能接收。 4.子网掩码子网掩码用于划分局域网。由于主机数量越来越多,出现了IP不够的情况。划分子网,让多台主机使用同一个公网IP,部分解决了这一问题。 5.域名IP地址有4段,不易记忆,通常给主机起一个名字,如127.0.0.1称为localhost,这就是127.0.0.1这个IP地址的域名。 四、通信协议 1.UDP协议1)概述UDP(user data protocol)向应用程序提供了一种发送封装的原始IP数据包的方法。该协议面向无连接,通信主机一端只负责发送数据,不负责对方是否接收到数据;如果对方处于在线状态,就能接收到数据包;如果不在线,该数据包就丢失。UDP在传输数据时,两通信主机不一定已经建立连接。 2)特点1> 将数据、数据源和目的封装成数据包;2> 数据包大小有限制,限制在64k以内;3> 不需要建立连接,协议不可靠4> 速度快,效率高 2.TCP协议1)概述TCP(transmission control protocol)是专门设计用于在不可靠的因特网上提供可靠的、端到端的字节流通讯协议。它是一种面向连接的协议。TCP与UDP协议相反,是面向连接的协议。该协议在传输数据前必须先建立连接。这个连接的建立是基于三次握手的机制之上的。三次握手确保了数据连接通路的存在,一旦通信双方有一方断开连接,数据传输即刻停止。 2)特点1> 数据传输大小无限制2> 通过三次握手机制确定连接通路畅通3> 必须建立连接,协议可靠4> 速度较慢,效率较低 五、网络编程常用类 1.Socket类1)概述网络编程其实就是Socket编程。Socket是为网络服务提供的一种机制,是通信得以进行的前提。通信两端的主机都有Socket,两端通信其实就是Socket间在通信,数据在两个Socket间通过IO进行传输。TCP和UDP协议,都是基于Socket进行数据传输。 2)不同协议的Socket创建每个传输协议都有自己建立传输端点的方式。下面进行不同协议的Socket服务的建立。 UDP协议建立发送端SocketDatagramSocket和DatagramPacket类DatagramSocket类表示用来发送和接收数据包的套接字(Socket)。该类既能发送,又能接收。DatagramSocket在发送数据时,提供了数据包对象DatagramPacket,用于数据封包。 第一步:建立发送端UDPSocket服务 第二步:提供数据,并将数据封装到数据包中 第三步:通过Socket服务发送数据包 第四步:关闭资源 UDP协议建立接收端Socket 第一步:建立接收端UDPSocket服务 第二步:定义数据包对象 第三步:通过Socket服务接收数据包 第四步:解析数据包 第五步:关闭资源 程序运行结果:127.0.0.1::UDP ge men er lai la !~~#!@$@%#^$&::64979 注意:UDP接收端的receive()方法是阻塞式方法…