首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

java基础巩固-详解泛型

java泛型(generics)为jdk5引入的新特性,泛型提供了编译时类型安全检测机制,可以在编译时检测到非法的类型。 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 使用泛型的好处 它的主要目标是保障java的类型安全,简化编程,泛型可以使编译器知道一个对象限定类型是什么,所有的强制转换都为自动和隐式的。 举个简单的栗子 public class test1 { public static void main(String[] args) { List list = new ArrayList(); list.add("字符串"); list.add(1); for (Object a : list) { System.out.println("toString转换->" + a.toString()); System.out.println("强转->" + (String)a); } } } 执行结果 Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String toString转换字符串 强转字符串 toString转换1 at generics.test1.main(test1.java:13) 虽然编译的时候没有报错,但是运行的时候强转为String的时候出现类型转换的错,可以看出来这种写法是不安全的。 进一步做点改良(使用泛型后,编译器报错,这样可以预防一些后续编译通过但运行报错的情况) 泛型的一个重要特性:跟反射不同的是,泛型检查只在编译期间有效,而反射则是在运行时有效。 下面做个简单的测试 public class test2 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //测试泛型 List<String> list1 = new ArrayList<String>(); List<Integer> list2 = new ArrayList<Integer>(); Class class1 = list1.getClass(); Class class2 = list2.getClass(); if(class1.equals(class2)) { System.out.println("类型相同"); } //测试反射 Map<String, String> map = new HashMap<String, String>(); String key = "key"; Integer val = 1; //通过反射获取方法 Method m = HashMap.class.getDeclaredMethod("put", new Class[] { Object.class, Object.class }); //invoke意在将方法参数化 动态调用Method类代表的方法 并传入参数 m.invoke(map, key, val); System.out.println(map); System.out.println(map.get(key)); //获取key为key的值 } } image.png 泛型的使用方式 1.泛型类 2.泛型接口 3.泛型方法 泛型类 //T,E,K,V等均表示为泛型 public class Generic<T> { private T key;//成员变量类型为T,由外部指定 public Generic(T key) { this.key = key; } public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 return key; } public static void main(String[] args) { //在实例化泛型类时 需指定T的具体类型(这边5就代表integer) Generic<Integer> s1 = new Generic<Integer>(5); Generic<String> s2 = new Generic<String>("5"); System.out.println(s1.getClass());//class generics.Generic System.out.println(s2.getClass());//class generics.Generic System.out.println(s1.getKey().getClass()); //class java.lang.Integer System.out.println(s2.getKey().getClass()); //class java.lang.String /** * 定义泛型类不一定要传入泛型类型实参,如果传入的化会在编译时做限制,不传的化可以为任一类型, * 但处于安全考虑一般都定义否则一些场景容易出现ClassCastException错误 */ Generic t1 = new Generic(5); Generic t2 = new Generic(0.5); System.out.println(t1.getKey()); //5 System.out.println(t2.getKey()); //0.5 System.out.println(t1.getKey().getClass()); //class java.lang.Integer System.out.println(t2.getKey().getClass()); //class java.lang.Double } } } 泛型接口 泛型接口与类定义和使用大致相同,例如Map接口的一小段代码 public interface Map<K,V> { ... V put(K key, V value); void putAll(Map<? extends K, ? extends V> m);//指明泛型的上边界 ... } 实现泛型接口,假设实现map //假如一个类实现了泛型接口,需要将泛型声明(test3<K,V>) 一起加到类中 否则编译报错 public class test3<K,V> implements Map<K,V>{ @Override public int size() { return 0; } @Override public boolean isEmpty() { return false; } ... } 泛型方法 泛型类,是在实例化类的时候指明【泛型】的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。 这样说有点绕口 举两个栗子 /** 泛型类 **/ //定义泛型类 该类 public class Test<T> { public T key; public test5(T key) { this.key = key; }; } //通过实例化指明【泛型】T的类型为String Test<String> t = new Test<Sring>("123"); /** 泛型方法 定义泛型方法时 必须在返回值前面加一个 <T> 来声明这是一个泛型方法 **/ public class test5<T> { //在这里<T>表示返回的类型是T的 该方法的作用是新建任一指定类型并返回 public <T> T getObject(Class<T> c) throws IllegalAccessException, InstantiationException { T t = c.newInstance();//创建泛型对象 return t; } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { test5 t = new test5(); //调用泛型方法【在调用方法的时指明泛型具体类型 这边用User型】 //在这object就是User的实例 这边测试别用类似java.lang.xxx这样BootStrap类加载器加载的类 否则输出为空 Object object = t.getObject(Class.forName("generics.User")); System.out.println(object.getClass()); //输出class generics.User } } 泛型的上下边界 使用泛型的时,可以通过传入泛型类型实参进行上下边界的限制。 如定义一个泛型类 public class Generic<T extends Number> { //此处为上边界 意为给定T类型需为Number子类 T super XX 为下边界 private T key; public Generic(T key) { this.key = key; } public T getKey(){ return key; } } 如果这样实例化Generic类编译器会报错,因为String不是Number的子类。 Generic<String> generic = new Generic<String>("11111"); 一些思考 1.下面这个getKey是否为泛型方法 public class Generic<T> { private T key; public Generic(T key) { this.key = key; } public T getKey(){ return key; } } 并不是,虽然在方法中使用了泛型,这个是类中普通的成员方法,因为它的返回值是声明泛型类【Generic】时已经声明过的泛型【T】,所以在方法中可以继续使用T这个泛型。 2.经常在使用泛型的代码中看见通配符 【?】它的作用是什么,和T的区别在哪呢 比如Map源码 void putAll(Map<? extends K, ? extends V> m); 在这里?是通配符,泛指所有类型,常用于不确定类型的情况 ? extends T 指T类型或T的子类型 ? super T 指T类型或T的父类型 它们的区别在于 "T"是定义类或方法时声明的东西,"?"是调用时传入的东西 ①T常用于声明一个泛型类或者泛型方法 ②?常用于使用泛型类或泛型方法 声明泛型类时不能用无界通配符<?> //error example class demo<?> { private ? item; } 通配符是可以用来使用定义好的泛型的 但是T不能用来继续使用已经定义好的泛型 当我们在外面使用一个带泛型T的类或方法时,T应该用一个实际的数据类型替代它,也可以使用?通配符 public class User { HashMap<T,String> map = new HashMap<String, String>(); //error example HashMap<?,String> map = new HashMap<String, String>(); //right example } 看hashMap源码中的putAll方法 简单来说,T一般是声明时用(泛型类,泛型方法),而?通配符一般是使用时用,可以使用作为通用类。

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

Java基础巩固-枚举的使用

枚举:jdk1.5引入的新特性,允许用常量表示特定的数据片段,且全一类型安全的形式来表示。 常用的定义常量方式 public static final xxx ...例如: public static final int SEASON_SPRING = 1; public static final int SEASON_SUMMER = 2; public static final int SEASON_FALL = 3; public static final int SEASON_WINTER = 4; 使用常量的缺点 1.类型不安全,若一个方法要求传入季节参数。 public Object getSeasonXXX(int seasonType) { ... return xxx; } //如果这个时候要调用getSeasonXXX根据传入的天气获取天气的一些相关属性,用常量的话,形参就是int类型,这个时候getSeasonXXX(SEASON_WINTER)和getSeasonXXX(4)都能获取冬天的天气属性,那么getSeasonXXX(5)也能编译过去而不会警告,但这样就不安全了。 2.没有命名空间。开发者要在命名的时候以SEASON_开头,另外一个开发者再看这段代码的时候,才知道这四个常量分别代表季节。 3.如果定义int值相同的变量,容易造成混淆。 使用枚举类 这个时候尝试利用枚举来定义常量,写个最简单的例子,例如 public enum SeasonEnum { SPRING,SUMMER,FALL,WINTER; } 将该类的编译后的class文件 javap(对编译的文件进行反编译)一下,可以看到类型默认继承java.lang.Enum 简单用法 public class testEnum1 { enum EnumW { SPRING,SUMMER,FALL,WINTER; } public static void main(String[] args) { EnumW enumW = EnumW.SPRING; System.out.println(enumW); //输出SPRING System.out.println(enumW); //输出SPRING if (enumW.equals(enumW.toString())) { //这边不会输出相同 因为enumW不是String类型 但是有equals、toString()方法 System.out.println("相同"); } } } 枚举类也可以定义属性和方法,例如 public class testEnum2 { enum EnumW { SPRING("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天");//枚举类的实例必须放在第一行,如果放在下面编译会报错 private final String name; private EnumW(String name) {//枚举类的构造器只能是私有的 这边改为public编译会有警告(可以自定义多个参数然后再get获取多个属性) this.name = name; } public String getName() { return name; } } public static void main(String[] args) { EnumW enumW = EnumW.SPRING; System.out.println(enumW.getName());//春天 } } 从上述例子可以看出枚举类的几个特点 enum和class、interface的地位一样 使用enum定义的枚举类默认继承了java.lang.Enum,而不是继承Object类。枚举类可以实现一个或多个接口。 枚举类的所有实例都必须放在第一行展示,不需使用new 关键字,不需显式调用构造器。自动添加public static final修饰。 使用enum定义、非抽象的枚举类默认使用final修饰,不可以被继承,又因为继承了Enum类不能再继承其它类。 枚举类的构造器只能是私有的。 枚举类的常用用法 1.可以在switch case语句中直接使用枚举值,不需加入枚举类作为限定,使代码更加优雅 public class testEnum3 { enum EnumW { SPRING,SUMMER,FALL,WINTER; } public void judge(EnumW s) { switch(s) { case SPRING: //直接使用枚举值做限定 System.out.println("春天适合踏青。"); break; case SUMMER: System.out.println("夏天要去游泳啦。"); break; case FALL: System.out.println("秋天一定要去旅游哦。"); break; case WINTER: System.out.println("冬天要是下雪就好啦。"); break; } } public static void main(String[] args) { EnumW enumw = EnumW.SPRING; testEnum testEnum = new testEnum(); testEnum.judge(enumw);//春天适合踏青。 } } 思考 1.枚举类是否可以定义抽象方法 首先有抽象方法的类必然是抽象类,但是根据上面的反编译的类由final修饰而不是抽象类,但是枚举类又可以定义抽象方法,这是为什么呢。 首先编写这么一段代码 public enum AbstractTest { Spring { @Override public AbstractTest getSeason() { return Spring; } }, Summer { @Override public AbstractTest getSeason() { return Summer; } }, FALL { @Override public AbstractTest getSeason() { return FALL; } }, WINTER { @Override public AbstractTest getSeason() { return WINTER; } }; public abstract AbstractTest getSeason(); public static void main(String[] args) { System.out.println(AbstractTest.Spring.toString());//Spring } } 查看编译后的文件 javac AbstractTest.java 将java文件编译为class文件,会生成4个从1开始包含$+数字的class文件(匿名内部类)和一个主类(枚举类),这四个类继承了主类从而通过子类来实现抽象方法 所以枚举类是可以带有抽象方法的,含有抽象方法的枚举类将自动修饰abstract并通过内部类来实现。

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

Python基础 ——简介、变量及类型

一.Python简介 1.Python的诞生 Python是目前世界上最流行的变成语言之一,由荷兰人Guido von Rossum(吉多·范·罗苏姆,中国Python程序员都叫他 龟叔)于制作。1991年,第一个Python编译器诞生。 2.Python编译器 Python目前有很多编译器,常用的有CPython(官方版本的C语言实现)、Jython(可以运行在Java平台)、IronPython(可以运行在.Net和Mono平台)、Pypy(Python实现的,支持JIT即时编译)。 3.Python版本 Python目前有两个版本,Python2和Python3,最新版本为Python2.7.13和3.6.2。 4.Python优缺点 优点:简单、易学、免费、开源、高层语言、可移植性高、解释型语言、面对对象、可扩展性强、丰富的库、规范的代码缺点:Python语言非常完善,几乎没有明显的短板和缺点,唯一的不足就是执行效率慢(这是解释型语言的通病),随着计算机性能的逐步提高,这个缺点也会逐渐不那么明显。 5.Python主要应用场景 (1)Web应用开发 (2)操作系统管理、服务器运维的自动化脚本 (3)网络爬虫 (4)科学计算 (5)桌面软件开发 (6)服务器软件开发 (7)游戏开发 (8)产品早期原型和迭代 二.第一个Python程序 1.Python文件 Python源程序就是一个特殊格式的文本文件,其后缀名为“.py”(即文件扩展名为 .py),因此可以用任意的文本编辑软件做Python的开发。 2.第一个Python程序 Step1.在桌面新建记事本文件,命名为FirstPython image.png 此时的文件是一个后缀扩展名为txt文档,并不是以.py结尾的文件Step2.修改文件扩展名为 .py image.png image.png 点击 是 ,即可将文件更改为Python文件Step3.使用文本编辑器打开(编辑器使用Sublime Text或NotePad++都行) image.png 保存并退出Step4.在windows下运行 按 windows + R 输入cmd 打开windows终端(俗称黑窗口) image.png image.png 三.执行Python程序的三种方式 1.文本模式 Python代码保存在文本文件中,Python解释器对其逐行解释,即上面演示打印“Hello,Python”的操作。 2.交互模式 直接在终端中运行解释器 image.png (1)交互执行Python程序的优缺点: 优点:适合于学习/验证Python语法或者局部代码 缺点:代码不能保存 不适合运行太大程序 (2)退出Python终端交互模式 ①直接输入 exit() 即可 image.png ②使用热键退出 Ctrl + z 也可退出 3.IPython IPython 是一个 python 的 交互式工具,比官方默认送的 python shell 好用,支持自动补全,自动缩进,内置了许多很有用的功能和函数,IPython 是开源免费的 Python 2.x 使用的解释器是 ipython Python 3.x 使用的解释器是 ipython3 要退出IPython可以有以下两种方式: (1) 直接输入 exit In [1]: exit (2)使用热键退出 在 IPython 解释器中,按热键 ctrl + d,IPython 会询问是否退出解释器 四.Python编辑器——PyCharm 1.PyCharm简介 (1)集成开发环境(IDE) IDE —— Integrated Development Environment 集成了开发软件需要的所有工具,一般包括:图形界面、代码编辑器、代码解释器、代码调试器等 (2)PyCharm介绍 1)PyCharm是Python的一款非常优秀的继承开发环境软件 2)PyCharm除了具备一般IDE所具备的功能外,还同时可以在Windows、Linux、MacOS等多个操作系统上使用。 3)PyCharm适合开发大型项目 五.PyCharm使用 1.第一次启动界面 image.png 2.创建一个项目 image.png 3.用PyCharm编写并运行第一个Python程序 image.png image.png image.png 六. 注释 1.注释的作用 注释可以大大提高代码的可读性。2.Python的两种注释方式 (1)单行注释 使用 # 进行单行注释,即#号后为注释内容 image.png (2)多行注释 使用一对三个单引号或双引号,引号中间即为注释,通过这种方法可一次注释多行 七. 变量及类型 1.变量 (1)变量的定义及作用 在Python中每个变量在使用前都必须赋值,变量赋值以后,变量才会被创建,变量使用 = 号赋值,= 号左边为变量名,= 号右边为存储在变量中的值。 形式如下: 变量名=变量值 变量可以理解为一个容器,用来存储数据。这就是变量的作用。 (2) Blog: www.limiao.tech

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

Go基础(复杂类型):指针

Go语言指针 Go 具有指针。 指针保存了变量的内存地址。 类型 *T 是指向类型 T 的值的指针。其零值是 nil。 var p *int & 符号会生成一个指向其作用对象的指针。 i := 42 p = &i * 符号表示指针指向的底层的值。 fmt.Println(*p) // 通过指针 p 读取 i *p = 21 // 通过指针 p 设置 i 这也就是通常所说的“间接引用”或“非直接引用”。 与 C 不同,Go 没有指针运算。 例如以下的例子: package main import "fmt" func main() { //定义一个变量i等于42 i := 42 //方式一 //&i指针,生成一个指针,指向作用对象i p := &i //*T符号表示指针指向的底层的值 fmt.Println(*p) //通过这个指针去操作i,去改变i的值 *p = 21 fmt.Println(i) //定义一个变量j,值为2701 j := 2701 //方式二 //&i指针,生成一个指针,指向作用对象i //*p(除后的值) = *p(2701)/37 p = &j *p = *p/37 fmt.Println(j) } 输出结果: 42 21 73 好啦,指针的学习就到此结束啦。

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

Java并发编程基础-理解中断

章节 什么是中断 中断线程的方法 线程中断状态的判断以及何时被中断的线程所处 isInterrupted() 状态为 false? 1.什么是中断 线程标识位 中断可以理解为线程的一个标识位属性,它标识一个运行中的线程是否被其他线程进行了中断操作。 2.中断线程的方法 其他线程通过调用该线程的 interrupt() 方法对其进行中断操作。 其实就是其他线程对该线程打了个招呼,要求其中断。 3. 线程中断状态的判断 线程通过方法isInterrupted()方法来进行判断是否被中断。 如下两种情况需要注意: 1.如果被中断的线程已经处于终结状态,那么调用该线程对象的 thread.isInterrupted() 返回的仍是 false。 2.在Java API中可以看到,许多抛出 InterruptedException 的方法,(其实线程已经终结了,因为遇到了异常)如Thread.sleep( long mills) 方法)这些方法在抛出InterruptedException 异常之前,JVM会将中断标识位清除,然后抛出InterruptedException,此时调用isInterrupted()仍会返回false。 package org.seckill.Thread; import java.util.concurrent.TimeUnit; public class Interrupted { public static void main(String[] args) throws InterruptedException{ Thread sleepThread = new Thread(new SleepRunner(),"sleepRunner"); sleepThread.setDaemon(true);//支持性线程 Thread busyThread = new Thread(new BusyRunner(),"busyRunner"); busyThread.setDaemon(true); sleepThread.start(); busyThread.start(); TimeUnit.SECONDS.sleep(5); sleepThread.interrupt(); busyThread.interrupt(); System.out.println("sleep Thread interrupted status is:"+sleepThread.isInterrupted()); System.out.println("busy Thread interrupted status is:"+busyThread.isInterrupted()); SleepUnit.second(500); } /** * 沉睡中的线程-静态内部类 */ static class SleepRunner implements Runnable { public void run() { while (true) { SleepUnit.second(10); } } } /** * 不停运行,空耗cpu的线程-静态内部类 */ static class BusyRunner implements Runnable { public void run() { while (true) { } } } /** * 静态内部工具类 */ static class SleepUnit { public static void second(int seconds) { try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } 运行结果: 运行结果 我们可以发现 sleep线程的 isInterrupted 状态为false,其中断标识位被清除了。 busy 线程属于正常中断所以isInterrupted 状态为 true,中断标识位没有被清除。

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

07.Java基础(泛型)

在类上定义泛型 类上定义的泛型是在对象实例化的时候指定的,可以用于类中定义的成员变量和成员方法,但是不包括静态成员变量和静态成员方法,因为静态变量和方法的调用可以通过类名实现,不需要创建类的对象,因此此时类上定义的泛型还没有被指定,所以静态不能使用类定义的泛型,相反对于普通成员变量和方法,它们的调用是通过类的对象来实现地,创建对象之后泛型已经被指定,所以它们可以和类的泛型保持一致 public class Tool<R> { //Cannot make a static reference to the non-static type R //public static R r; public R r; public void setR(R r) { this.r = r; } public R getR() { return r; } } 在方法上定义泛型 方法上使用的泛型可以和类泛型保持一致,比如我们上边得到setR getR方法,也可以设置和类泛型不同的泛型,如下便setParam方法泛型Z的指定,这样在调用这个方法的时候就可以你指定什么泛型就设置什么类型,但是这样操作似乎意义不大,方法泛型最好和类泛型保持一致 public class Tool<R> { public R r; public void setR(R r) { this.r = r; } public R getR() { return r; } //这种使用形式会报错:Z cannot be resolved to a type //因为Z泛型并没有被定义,正确的方式是下边 //public void setParam(Z z) { //}; //把泛型指定在方法返回值类型的前边,注意不可以是后边 public <Z>void setParam(Z z) { }; } 在静态方法上使用泛型 静态方法随着类的加载就已经存在,所以先于对象的创建,因此不能使用类上定义的泛型,类泛型是在创建对象的时候指定的,静态方法泛型在调用静态方法的时候指定 public class Tool<R> { public R r; public void setR(R r) { this.r = r; } public R getR() { return r; } //public void setParam(Z z) { //}; public <Z>void setParam(Z z) { }; //同样这种使用形式会报错:M cannot be resolved to a type //因为Z泛型并没有被定义,正确的方式是下边 //public static void setData(M m) { //} //静态方法的泛型要定义在返回值的左边,static关键字的右边 public static <M>void setData(M m) { } } 在接口上使用泛型 在接口上定义泛型的目的很简单,就是对实现类做限制,保证规则的统一 定义接口中所有方法都可以使用的泛型,接口中可能存在多个方法,这样一来每个方法都可以使用这个泛型 public interface Inter<R> { void process(R r); } class Demo implements Inter<String>{ @Override public void process(String r) { } } 针对接口中单独的方法指定独有的泛型 public interface Inter { <R>void process(R r); } class Demo implements Inter{ @Override public <R> void process(R r) { } } 接口中虽然定义了泛型,但是我操作实现类的时侯再指定这个实现类特定的泛型,这样做是可行的,但是没有实际意义 public interface Inter<R> { void process(R r); } class Demo<Z> implements Inter<Z>{ @Override public void process(Z r) { // TODO Auto-generated method stub } } 泛型通配符<?> <?>表示任意类型,如果没有明确指定那就是Object以及任意的Java类 通配符的两种使用场景 ?extends E : 向下限定,固定上边界,E及其子类 ? super E :向上限定,固定下边界,E及其父类 向下限定,E及其子类 Colloection的addAll方法 addAll(Colloction<? extends E> c); //student是person的子类,所以可以调用addAll方法添加 ArrayList<Person> list1 = new ArrayList<>(); ArrayList<Student> list2 = new ArrayList<>(); list1.addAll(list2); 向上限定,固定下边界,E及其父类 TreeMap构造方法 TreeMap(Comparator<? super K> comparator)

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

多线程之并发基础(三)

线程是轻量级的进程,进程可以说是线程的容器。线程是程序执行的最小单位。使用多线程而不是使用多进程进行并发程序的设计,因为线程的切换和调度成本远远小于进程。 与文无关 本文知识点目录: 线程的状态 线程的常见操作 Daemon线程 线程优先级 wait与notify 线程的状态 在Java程序中,线程有如下状态 NEW(新建): 新的线程刚刚创建,还没有启动。 Runnable(就绪):线程已经调用了start方法,正在被JVM执行的时候,也有可能正在等待某个操作系统的资源。 Blocked(阻塞):有其它线程占着锁不释放,当前线程阻塞与锁 Waiting(等待):表示当前线程需要等待其它线程做出一些特定动作(通知或中断),当调用以下方法时会进入此状态。 Object.wait()没有时间参数 Thread.join()没有超时参数 LockSupport.park方法 Timed Waiting(等待并计时):指定时间waiting,一边等,一边计时,一般调用如下方法可以j进入此状态。 Thread.sleep Object.wait()带有参数 Thread.join ()带有超时参数 LockSupport.parkNanos LockSupport.parkUntil Terminated(终止) 线程完成了它的操作,也有可能错误的执行而终止。 线程状态图 线程状态图 线程操作 实现多线程 我们想要实现多线程常用的有两种方法 实现Runnable接口 继承自Thread线程 java只能单继承,因此如果是采用继承Thread的方法,那么在以后进行代码重构的时候可能会遇到问题,因为你无法继承别的类了。 如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。 注意这是在多线程情况下, 每个人运行的结果可能都不一样。要想保住线程安全性,还需要额外的操作。 // 案例代码,继承线程变量无法共享 public class ThreadOrRunnable extends Thread { private int count=5; private String name; public ThreadOrRunnable(String name) { this.name=name; } @Override public void run() { // super.run(); for (int i = 0; i < 5; i++) { count--; System.out.println(name + "运行 count=" + count); } } public static void main(String[] args) { ThreadOrRunnable threadOrRunnable = new ThreadOrRunnable("A"); ThreadOrRunnable threadOrRunnableB = new ThreadOrRunnable("B"); threadOrRunnable.start(); threadOrRunnableB.start(); } } //运行结果: A运行 count=4 A运行 count=3 A运行 count=2 A运行 count=1 B运行 count=4 A运行 count=0 B运行 count=3 B运行 count=2 B运行 count=1 B运行 count=0 // 案例 继承自Runnable可以共享count变量 public class RunnableTest implements Runnable{ private int count=15; @Override public void run() { for (int i = 0; i < 5; i++) { count--; System.out.println(Thread.currentThread().getName() + "运行: count=" + count); } } public static void main(String[] args) { RunnableTest runnableTest = new RunnableTest(); new Thread(runnableTest,"A").start(); new Thread(runnableTest,"B").start(); } } // 运行结果 B运行: count=13 A运行: count=13 B运行: count=12 A运行: count=11 B运行: count=10 A运行: count=9 A运行: count=7 A运行: count=6 B运行: count=8 B运行: count=5 Daemon线程 Daemon线程是一种支持型线程,在后台调度及支持性工作。它有两个点需要注意: 必须在程序调用start方法之前调用Thread.setDaemon(true)方法才能设置为daemon线程,如果start()之后设置,会报IllegalThreadStateException异常 在所有前台线程执行完毕的时候,daemon线程会自动销毁。 Thread thread = new Thread(); thread.setDaemon(true); thread.start(); 线程优先级 Java中的线程可以有自己的优先级,优先级高的线程在竞争资源时更可能抢占资源,但是这只是一个概览问题,并不是谁的优先级高,谁就一定先执行。 Thread thread = new Thread(); // MIN_PRIORITY = 1; // NORM_PRIORITY = 5; // MAX_PRIORITY = 10; thread.setPriority(int newPriority) thread.start(); wait与notify wait和notify方法不是在Thread类中的,而是在Object类中,意味着任何对象都可以调用这两个方法。 当一个线程A调用了obj.wait()方法,那么线程A就会停止继续执行,而是转为waiting状态。一直都其它线程调用obj.notify()方法为止。 notify与notifyAll 注意: notify方法是从等待队列中的线程随机选择一个,我们无法保证它唤醒的是那一个。notifyAll()方法会唤醒所有等待的线程。 object.wait()方法必须包含在synchronized语句中,wait或notify都需要首先获得目标对象的监视器。 Object.wait和Thread.sleep方法都可以让线程等待若干时间,它们哟徐诶区别。 wait可以被唤醒,sleep不可以 wait会释放目标对象的锁,而sleep不释放任何锁。 public class WaitNotify { static volatile boolean flag = true; static Object lock = new Object(); static class Wait implements Runnable{ @Override public void run() { synchronized (lock){ while (flag){ System.out.println(Thread.currentThread().getName() + " 时间: " + System.currentTimeMillis()); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //条件满足的时候完成了工作 System.out.println("flag=" + flag + "任务完成"); } } } static class Notify implements Runnable{ @Override public void run() { synchronized (lock){ System.out.println(Thread.currentThread().getName() + " 持有锁"); lock.notifyAll(); flag = false; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (lock){ System.out.println("再次持有锁"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { Thread waitThread = new Thread(new Wait(),"waitThread"); waitThread.start(); TimeUnit.SECONDS.sleep(1); Thread notifyThread = new Thread(new Notify(),"notifyThread"); notifyThread.start(); } } //运行结果,调用notify之后,wait状态会变为blocked状态,然后再进入Runnable状态。 运行结果 Wait与notify可以提炼出等待/通知的经典范式,氛围两部分: 等待方规则: 获取对象的锁 如果条件不满足,那么调用wait方法,被通知后仍要检查条件 条件满足则执行相应的逻辑 通知方规则: 获得对象的锁 改变条件 通知等待对象上的线程。 问题 关于Object.wait与notify,最后再留下来一个问题: 为什么wait与notify方法要在Object类中调用而不是在Thread中? 最后 这次提到了一些Thread的基本概念,线程的状态切换,线程的两个属性,最后提了一下wait与notify方法。下次讲一下线程的常见用法。 参考 Lifecycle and States of a Thread in Java 《Java并发编程的艺术》 《Java高并发程序设计》

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

Linux基础 crontab定时任务

linux定时任务: 程序、进程、守护进程 程序:软件,可执行的代码 进程:正在执行的命令、服务,执行完成,就会退出 守护进程(服务):在后台一直运行的进程 sshd: 守护进程:daemon 1)检查crond服务是否允许 /etc/init.d/crond status /etc/init.d/crond start chkconfig crond on 2)定时任务的写法 * * * * * cmd 分 时 日 月 周 执行的命令 3)举例 编辑定时任务crontab -e * * * * * echo 1234567 >>/tmp/oldboy.txt 查看定时任务crontab -l 练习: 每隔两个小时,重启一下sshd服务 4)定时任务 一定要,命令行,先测试!!! 10 */2 * * * 每隔2小时的每分钟,都执行 5)定时任务的取值范围 * * * * * cmd 分 时 日 月 周 执行的命令 0-59 0-23 1-31 1-12 0-6 练习: 每周3,下午6点整,echo jiaozuoye 00 18 * * 3 6)注意 */3 每隔多久执行一次 7)例子: 每天下午的2点整和4点整,京东秒杀 echo jingdongmiaosha 00 14,16 * * * echo jingdongmiaosha 练习: 每年的3、6、11月份,1-7号,早上8点整到晚上8点整 echo 进行大酬宾 00 8-20 1-7 3,6,11 * echo dachoubin 8:注意事项 a.定时任务执行命令的时候,最好使用命令的决对路径。 b.定时任务一定要加注释!(君子协议) c.特殊符号需要转义;例子:* * * * * echo "`date +\%F\ \%T`" >>/tmp/time.txt d.最好不要让直行的命令,有输出,如果避免不了有输出,就把它定向到空(黑洞) e.定时任务中,严禁使用相对路径 f.尽量使用crontab -e命令来添加定时任务!因为crontab带有语法检查。 不加引号:只能输出单行文本;能解析变量 单引号: 可以输出多行文本; 不能解析变量,适合输出带有特殊符号的内容 双引号: 可以输出多行文本;能解析变量 标准输出:1>(默认就是标准输出) 错误输出:2> 黑洞:/dev/null 9:批量添加定时任务 crontab -e编辑定时任务,实际上就是编辑文件/var/spool/cron/root #上课 30 9 * * 0 /oldboy.sh &>/dev/null echo -e '#上课\n30 9 * * 6 /oldboy.sh &>/dev/null' >>/var/spool/cron/root 建个回收站recovery alias rm = "mv -f -t /recovery" 直接删除\rm \取消别名作用 crontab -e * */2 * * * \rm -rf /recovery/* #每两小时清空一次recovery minute hour day month dayofweek command minute是分钟,取值范围:0-59 hour段是小时。取值范围:0-23 day段是一个月中的第几天,取值范围:1-31 month是一年中的第几个月,取值范围:1-12 dayofweek是一个星期中的第几天,以星期天开始依次的取值为0~7,0、7都表示星期天。 command是定时运行的命令。 root表示以root用户身份来运行 run-parts表示后面跟着的是一个文件夹,要执行的是该文件夹下的所有脚本 所有可用值用 * 表示 整数间的连字号(-)表示整数列,例如1-4意思是整数1,2,3,4 指定数值由逗号分开。如:3,4,6,8表示这四个指定整数。 符号“/”指定步进设置。“/<interger>”表示步进值。如0-59/2定义每两分钟执行一次。步进值也可用星号表示。如*/3用来运行每三个月份运行指定任务。 以“#”开头的为注释行,不会被执行。 如果一个cron任务需要定期而不是按小时,天,周,月来执行,则需要添加/etc/cron.d目录。这个目录下的所有文件和文件/etc/crontab语法相同,查看样例: # record the memory usage of the system every monday # at 3:30AM in the file /tmp/meminfo 30 3 * * mon cat /proc/meminfo >> /tmp/meminfo # run custom scrīpt the first day of every month at 4:10AM 10 4 1 * * /root/scrīpts/backup.sh 除了root用户之外的用户可以执行crontab配置计划任务。所有用户定义的crontab存储在目录/var/spool/cron下,任务会以创建者的身份被执行。要以特定用户创建一个crontab,先以该用户登录,执行命令crontab -e,系统会启动在VISUAL或者EDITOR中指定的的编辑软件编辑crontab。文件内容与/etc/crontab格式相同。示例如下: 0 3 * * * /home/dbbackup/db1backup.sh backup 0 4 * * * /home/dbbackup/db2backup.sh backup 表示每天3点执行/home/dbbackup/db1backup.sh backup,4点执行/home/dbbackup/db2backup.sh backup,如果是每五分钟执行一次可改为: */5 * * * * /home/dbbackup/db2backup.sh backup 当更改的crontab需要保存时,文件会保存在成如下文件/var/spool/cron/username。文件名会根据用户名而不同。 cron服务会每分钟检查一次/etc/crontab、/etc/cron.d/、/var/spool/cron文件下的变更。如果发现变化,就会下载到存储器中。因此,即使crontab文件改变了,程序也不需要重新启动。推荐自定义的任务使用crontab -e命令添加,退出后用/etc/init.d/crond restart命令重启crond进程,官方文件说不用重启进程,但我遇到不重启无法运行任务的情况。开始不知道/etc/crontab文件中的run-parts是什么意思,直接把命令按照/etc/crontab的格式加上总是无法运行,后来才知道run-parts是指后面跟着的是文件夹。 四.crontab服务的启动关闭 sbin/service crond start //启动服务 /sbin/service crond stop //关闭服务 /sbin/service crond restart //重启服务 /sbin/service crond reload //重新载入配置

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

java基础学习_常用类小结

看看下面的类,是否都熟悉,简要说明每个类主要是干什么呢? Object:是类层次结构的根类,所有类都直接或者间接的继承自该类。 Scanner:获取键盘录入数据的类。 String:针对字符串的常见操作的类。 StringBuffer/StringBuilder:字符串缓冲区类,提高字符串的操作效率。 Arrays:针对数组进行操作的工具类。 Integer:把int基本数据类型封装成Integer引用数据类型,可以调用方法了,最主要作用是可以把String引用数据类型转换int基本数据类型了。 Character:把char基本类型封装成Character引用数据类型,可以调用方法了。了解几个方法就可以了。 Pattern:正则表达式的编译表示形式。模式对象。 Matcher:匹配器对象。 Math:针对数学运算操作的类。 Random:产生随机数的类。 System:系统类,提供了几个有用方法。 BigInteger:关于大整数的运算的类。 BigDecimal:关于浮点数的运算用这个,不会有精度的丢失。 Date:针对日期操作的类,可以精确到毫秒。 DateFormat:针对日期进行格式化或者针对字符串(文本)进行解析的类。 Calendar:日历类,把所有的日历字段(成员变量)进行了封装,要什么,自己使用获取方法,然后拼接。 Object:是类层次结构的根类,所有类都直接或者间接的继承自该类。 Scanner:获取键盘录入数据的类。 String:针对字符串的常见操作的类。 StringBuffer/StringBuilder:字符串缓冲区类,提高字符串的操作效率。 Arrays:针对数组进行操作的工具类。 Integer:把int基本数据类型封装成Integer引用数据类型,可以调用方法了,最主要作用是可以把String引用数据类型转换int基本数据类型了。 Character:把char基本类型封装成Character引用数据类型,可以调用方法了。了解几个方法就可以了。 Pattern:正则表达式的编译表示形式。模式对象。 Matcher:匹配器对象。 Math:针对数学运算操作的类。 Random:产生随机数的类。 System:系统类,提供了几个有用方法。 BigInteger:关于大整数的运算的类。 BigDecimal:关于浮点数的运算用这个,不会有精度的丢失。 Date:针对日期操作的类,可以精确到毫秒。 DateFormat:针对日期进行格式化或者针对字符串(文本)进行解析的类。 Calendar:日历类,把所有的日历字段(成员变量)进行了封装,要什么,自己使用获取方法,然后拼接。我的GitHub地址: https://github.com/heizemingjun 我的博客园地址: http://www.cnblogs.com/chenmingjun 我的蚂蚁笔记博客地址: http://blog.leanote.com/chenmingjun Copyright ©2018 黑泽明军 【转载文章务必保留出处和署名,谢谢!】

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

02.Java基础(线程池)

执行异步任务的时候,如果只是new Thread,存在一下弊端 a. 每次new Thread新建对象性能差。 b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。 c. 缺乏更多功能,如定时执行、定期执行、线程中断。 Java本身提供了四种线程池 newCachedThreadPool 创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程, 那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智 能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于 操作系统(或者说JVM)能够创建的最大线程大小。 newCachedThreadPool是存在内存溢出安全隐患的,因为我们假设新建的线程都在工 作,newCachedThreadPool 只会重用空闲并且可用的线程,所以当所需线程数量足够大 时,会不停地创建新线程,在 64-bit JDK 1.7 中 -Xss 默认是 1024k,也就是 1M(一个线 程占用的空间大小),那就是需要 10000*1M = 10G 的堆外内存空间来给线程使用,就 会 发生OOM ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(index); } }); newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index = i; fixedThreadPool.execute(new Runnable() { @Override public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.schedule(new Runnable() { @Override public void run() { System.out.println("delay 3 seconds"); } }, 3, TimeUnit.SECONDS); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("delay 1 seconds, and excute every 3 seconds"); } }, 1, 3, TimeUnit.SECONDS); newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行 ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; singleThreadExecutor.execute(new Runnable() { @Override public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); 相对于直接new Thread,线程池具有一下优点 a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。 b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。 c. 提供定时执行、定期执行、单线程、并发数控制等功能

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

JavaScript的常用基础知识

前言 稻光养晦,未雨绸缪 函数的定义 函数定义的第一种方式 屏幕快照 2018-01-26 17.39.05.png 说明 1 . 这是最正常的一种函数表达式 2 . 函数aa可以接受任意的参数 3 . 可以有返回值,可以用变量来接受其返回值 4 . 如果没有return,则返回undefined. 函数定义的第二种方式 屏幕快照 2018-01-26 17.41.48.png 说明 1 . 直接给变量赋值一个函数 2 . 在项目开发中是一种比较常见的形式 Dom对象 DOM是Document Object Model文档对象模型的缩写。根据W3C DOM规范,DOM是一种与浏览器,平台,语言无关的接口,使得你可以访问页面其他的标准组件。 D:文档 – html 文档 或 xml 文档 O:对象 – 把document里的所有节点都看成对象 M:模型(用于建立从文档到对象的模型) 结构如下: 屏幕快照 2018-01-27 00.02.59.png 对应的html页面: 屏幕快照 2018-01-27 00.03.11.png 从上述两个图中可以看出: 1 . 整个html称为dom树,而dom的引用为document,也称为一个节点。 2 . 每一个HTML标签都为一个元素节点 3 . 标签中的文字则是文本节点 4 . 标签中的属性则是属性节点 5 . dom中元素、文本、属性都是节点 6 . dom树是由节点构成的 7 . 每个节点都代表一个对象 常用的API getElementById() 说明: 1、 查询给定ID属性值的元素,返回该元素的元素节点。也称为元素对象。 2、 因为在一个html页面中id的值是唯一的,所以返回值也是唯一的。所以方法的名称为getElementById()而不是getElementsById()。 3、 该方法只能用于document对象,类似与java的static关键字。 例子 屏幕快照 2018-01-27 00.24.44.png getElementsByName() 说明: 1、查找给定name属性的所有元素,这个方法将返回一个节点集合,也可以称为对象集合。 2、这个集合可以作为数组来对待,length属性的值表示集合的个数。 3、因为在html页面中,name不能唯一确定一个元素,所以方法的名称为getElementsByName而不是getElementByName。 例子 屏幕快照 2018-01-27 00.25.53.png getElementsByTagName() 说明: 1、查询给定标签名的所有元素 2、因为在html页面中,标签名不是唯一的,所以返回值为节点的集合。 3、这个集合可以当做数组来处理,length属性为集合里所有元素的个数 例子 <!DOCTYPE html> <html> <head> <title>getElementsByTagName.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <form name="form1" action="test.html" method="post"> <input type="text" name="halo" value="我是Halo1!!!" id="halo1"> <input type="text" name="halo" value="我是Halo2!!!" id="halo2"> <input type="text" name="halo" value="我是Halo3!!!" id="halo3"> <input type="text" name="halo" value="我是Halo4!!!" id="halo4"> <input type="button" name="ok" value="OK"> </form> <select name="sport" id="sport"> <option value="篮球">乔丹</option> <option value="足球" selected="selected">梅西</option> <option value="乒乓球">刘国梁</option> <option value="台球">丁俊晖</option> </select> <select name="edu" id="edu"> <option value="专科">专科学位</option> <option value="本科">本科学位</option> <option value="硕士">硕士学位</option> <option value="博士">博士学位</option> </select> </body> <script type="text/javascript"> /*** *1、获取所有input元素的值 *2、输出所有input元素的值,不包括按钮,并且点击文本框,获取相应的值。 *3、输出所有下拉选 id=“edu” 的value值 *4、输出所有下拉选框的内容 *5、选择下拉列表框的内容,并且弹出所选择的内容 *6、针对每一个下拉列表框的内容,弹出所选中的内容 ***/ //1. /******************************************************************/ /* //1.获取所有input元素的值 var inputElements = document.getElementsByTagName("input"); //遍历inputElements数组元素的每一个对象 for(var i=0;i < inputElements.length;i++){ alert(inputElements.item(i).value); } */ //2. /******************************************************************/ //输出所有input元素的值,不包括按钮,并且点击文本框,获取相应的值。 //1、获取input元素的对象数组 var inputElements = document.getElementsByTagName("input"); //2、遍历数组 /* for(var i=0;i<inputElements.length;i++){ if(inputElements[i].type != "button"){ alert(inputElements[i].value); inputElements[i].onclick = function(){ alert(this.value); } } } */ //3. /******************************************************************/ //输出所有下拉选 id=“edu” 的value值 //eduElement.childNodes获取的是所有子节点及子子节点。 /* //1、获取id为edu的对象 var eduElement = document.getElementById("edu"); //2、获取id为edu的对象的子节点 var optionElements = eduElement.getElementsByTagName("option"); for(var i=0;i<optionElements.length;i++){ alert(optionElements[i].value); } */ //4. /******************************************************************/ //输出所有下拉选框的内容 /* var optionElements = document.getElementsByTagName("option"); for(var i=0;i<optionElements.length;i++){ alert(optionElements[i].value); } */ //5. /******************************************************************/ //选择下拉列表框的内容,并且弹出所选择的内容 //1.获取所有的select元素的对象 var selectElements = document.getElementsByTagName("select"); //2.遍历所有的select对象,并且赋值onchange方法 for(var i=0; i<selectElements.length;i++){ selectElements[i].onchange = function(){ //this代表选中的option对象 alert(this.value); } } //6. /******************************************************************/ //针对每一个下拉列表框的内容,弹出所选中的内容 var selectElement1 = document.getElementById("sport"); var selectElement2 = document.getElementById("edu"); selectElement1.onchange = function(){ alert(this.value); } selectElement2.onchange = function(){ alert(this.value); } </script> </html> hasChildNodes() 说明 1、该方法用来判断一个元素是否有子节点。 2、返回值为true或者false。 3、文本节点和属性节点不可能再包含子节点,所以对于这两类节点使用 hasChildNodes()方法返回值永远为false。 4、如果hasChildNodes()返回值为false,则childNodes,firstChild,lastChild将为空数组或者空字符串。 例子 <!DOCTYPE html> <html> <head> <title>hasChildNodes.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <form name="form1" action="test.html" method="post"> <input type="text" name="halo" value="我是Halo1!!!" id="halo1"> <input type="text" name="halo" value="我是Halo2!!!" id="halo2"> <input type="text" name="halo" value="我是Halo3!!!" id="halo3"> <input type="text" name="halo" value="我是Halo4!!!" id="halo4"> <input type="button" name="ok" value="OK"> </form> <select name="edu" id="edu"> <option value="专科">专科学位</option> <option value="本科">本科学位</option> <option value="硕士">硕士学位</option> <option value="博士">博士学位</option> </select> </body> <script type="text/javascript"> /* *分两种情况输出hasChildNodes()的值 * 1、有子节点 * 2、没有子节点 */ //输出有子节点的值 var eduElement = document.getElementById("edu"); //因为有子节点,所以返回值为true alert(eduElement.hasChildNodes()); //输出没有子节点的值 var halo1Element = document.getElementById("halo1"); alert(halo1Element.hasChildNodes()); </script> </html> nodeName属性 说明 1、文档中的每一个节点都有这个属性。 2、为给定节点的名称。 3、如果节点是元素节点,nodeName返回元素的名称;如果给定节点为属性节点,nodeName返回属性的名称;如果给定节点为文本节点,nodeName返回为#text的字符串; 例子 <!DOCTYPE html> <html> <head> <title>nodeName.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <select name="edu" id="edu"> <option value="本科">本科学位</option> <option value="硕士">硕士学位</option> <option value="博士">博士学位</option> <option value="专科">专科学位</option> </select> </body> <script type="text/javascript"> /* *分别输出edu元素节点元素及属性name,id的nodeName * */ //1.获得edu对象 var eduElement = document.getElementById("edu"); //2.获得edu对象的nodeName alert(eduElement.nodeName); //这一步获得的是<select name="edu" id="edu">的name属性的值 //var nameElement = eduElement.name; //通过eduElement.getAttributeNode()可以获取属性的对象 var nameElement = eduElement.getAttributeNode("name"); alert(nameElement.nodeName); var idElement = eduElement.getAttributeNode("id"); alert(idElement.nodeName); var optionElements = eduElement.getElementsByTagName("option"); for(var i=0;i<optionElements.length;i++){ alert(optionElements[i].nodeName); var valueElement = optionElements[i].getAttributeNode("value"); alert(valueElement.nodeName); } </script> </html> nodeType属性 说明 1、该节点表明节点类型,返回值为一个整数 2、常用的节点类型有三种: (1)、 元素节点类型 值为1 (2)、属性节点类型 值为2 (3)、文本节点类型 值为3 例子 <!DOCTYPE html> <html> <head> <title>nodeName.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <select name="edu" id="edu"> <option value="专科">专科学位</option> <option value="本科">本科学位</option> <option value="硕士">硕士学位</option> <option value="博士">博士学位</option> </select> </body> <script type="text/javascript"> /* *分别输出edu元素节点元素及属性name,id的nodeType *输出option元素的子节点文本元素的元素类型 */ //1.分别输出edu元素节点元素及属性name,id的nodeType var eduElement = document.getElementById("edu"); //alert(eduElement.nodeType); var nameElement = eduElement.getAttributeNode("name"); //alert(nameElement.nodeType); var idElement = eduElement.getAttributeNode("id"); //alert(idElement.nodeType); var optionElements = eduElement.getElementsByTagName("option"); for(var i=0;i<optionElements.length;i++){ //alert(optionElements[i].nodeType); var valueElement = optionElements[i].getAttributeNode("value"); alert(valueElement.nodeType); var textElement = optionElements[i].firstChild; alert(textElement.nodeType); } </script> </html> nodeType属性 说明 1、返回给定节点的当前值(字符串)。 2、如果给定节点是属性节点,返回值是这个属性的值;如果给定节点是文本节点,返回值是这个文本节点的内容;如果给定节点是元素节点,返回值是null。 3、nodeValue是一个读写属性。 例子 <!DOCTYPE html> <html> <head> <title>nodeValue.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <select name="edu" id="edu"> <option value="专科">专科学位</option> <option value="本科">本科学位</option> <option value="硕士">硕士学位</option> <option value="博士">博士学位</option> </select> </body> <script type="text/javascript"> /* *分别输出edu元素节点元素及属性name,id的nodeValue *输出option元素的子节点文本元素的元素类型 */ //1、获得edu的元素节点 var eduElement = document.getElementById("edu"); //2、获得eduElement的nodeValue的值 alert(eduElement.nodeValue); //获得edu属性name的元素节点值 var nameElement = eduElement.getAttributeNode("name"); alert(nameElement.nodeValue); //获得edu属性id的元素节点值 var idElement = eduElement.getAttributeNode("id"); alert(nameElement.nodeValue); //输出option元素的子节点文本元素的元素类型 var optionElements = eduElement.getElementsByTagName("option"); for(var i = 0; i < optionElements.length; i++){ var valueElement = optionElements[i].getAttributeNode("value"); alert(valueElement.nodeValue); var textElement = optionElements[i].firstChild; alert(textElement.nodeValue); } </script> </html> replaceChild() 说明 1、把一个给定父元素里的一个子节点替换为另外一个子节点; 2、var reference = element.replaceChild(newChild,oldChild); 3、返回值指向已经被替换掉的那个子节点的引用; 例子 <!DOCTYPE html> <html> <head> <title>replaceChild.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> 您喜欢的城市:<br> <ul> <li id="wh" value="wuhan">武汉</li> <li id="km" value="kunming">昆明</li> <li id="sz" value="shenzhen">深圳</li> </ul> 您喜欢的词语:<br> <ul> <li id="six" value="sixsixsix">666</li> <li id="dy" value="daye">大爷</li> <li id="ly" value="laoye">老爷</li> </ul> </body> <script type="text/javascript"> /* *点击北京节点,将被给力节点替换 */ window.onload = function(){ //1、得到北京节点 var whElement = document.getElementById("wh"); //2、注册onclick事件 whElement.onclick = function(){ //3、找到wh节点的父节点 var ulElement = whElement.parentNode; //4、获得gl节点 var dyElement = document.getElementById("dy"); //5、替换 ulElement.replaceChild(dyElement,whElement); } } </script> </html> getAttribute() 说明 1、返回一个给定元素的给定属性的节点的值 2、var attributeValue = element.getAttribute(attributeName) 3、给定属性的名字必须以字符串的形式传递给该方法 4、给定属性的值将以字符串的形式返回 5、通过属性获取属性节点getAttributeNode(属性的名称) --返回属性节点 例子 <!DOCTYPE html> <html> <head> <title>getAttribute.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> 您喜欢的词语:<br> <ul> <li id="six" value="sixsixsix">666</li> <li id="dy" value="daye">大爷</li> <li id="ly" value="laoye">老爷</li> </ul> </body> <script type="text/javascript"> /** ** 获取<li id="six" value="sixsixsix">666</li>的属性id和value的值 **/ var sixElement = document.getElementById("six"); //第一种方法: alert(sixElement.getAttributeNode("id").nodeValue); alert(sixElement.getAttributeNode("value").nodeValue); //第二种方法: alert(sixElement.getAttribute("id")); alert(sixElement.getAttribute("value")); </script> </html> setAttribute() 说明 1、将给定元素添加一个新的属性或改变它现有属性的值; 2、element.setAttribute(attributeName,attributeValue); 3、属性的名字和值必须以字符串的形式传递; 4、如果这个属性已经存在,那么值将被attributeValue取代; 5、如果这个属性不存在,那么先创建它,再给他赋值; 例子 <!DOCTYPE html> <html> <head> <title>setAttribute.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> 您喜欢的词语:<br> <ul> <li id="six" value="sixsixsix">666</li> <li id="dy" value=daye"">大爷</li> <li id="ly" value="laoye">老爷</li> </ul> </body> <script type="text/javascript"> /** ** 给<li id="ly" value="laoye">老爷</li>增加一个name属性,并赋值,然后输出 **/ var lyElement = document.getElementById("ly"); lyElement.setAttribute("name", "halo"); alert(lyElement.getAttribute("name")); </script> </html> createElement() 说明 1、按照给定的标签名创建一个新的元素节点,方法的参数为被创建的元素的名称; 2、var reference = document.createElement(elementName); 3、方法的返回值指向新建节点的引用,返回值是一个元素节点,所以nodeType 为1; 4、新建的节点不会自动添加到文档里,只是存在于document里一个游离的对象; 例子 <!DOCTYPE html> <html> <head> <title>createElement.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> 您喜欢的词语:<br> <ul> <li id="six" value="sixsixsix">666</li> <li id="dy" value=daye"">大爷</li> <li id="ly" value="laoye">老爷</li> </ul> </body> <script type="text/javascript"> /** ** 为ul增加一个新的元素<li id="cs" value="cs">计算机</li> ** **/ //1.创建<li></li> var liElement = document.createElement("li"); //2.创建文本节点 传说 var textElement = document.createTextNode("计算机"); //3.<li id="cs" value="cs">计算机</li>的形成 liElement.appendChild(textElement); liElement.setAttribute("id", "cs"); liElement.setAttribute("value", "cs"); //4.获得ul对象 var ulElement = document.getElementsByTagName("ul")[0]; ulElement.appendChild(liElement); </script> </html> innerHTML属性 说明 用来读写某个元素中的HTML内容 例子 <!DOCTYPE html> <html> <head> <title>innerHTML.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <div id="mydiv"><h1 id="h">halo是我的简称!!</h1></div> </body> <script type="text/javascript"> /** *读取div中的html内容 **/ var divElement = document.getElementById("mydiv"); var h1Element = document.getElementById("h") alert(divElement.textContent); alert(h1Element.textContent); </script> </html> window.onload 说明 1、在页面上所有的数据加载完以后触发该方法; 2、这样做的好处是,有时候一些JS函数要用到页面上的一些数据,但是此时有些数据还没有加载进来。这个时候触发函数,就会报一些异常。所以用window.onload方法可以确保数据安全落地; 例子 <!DOCTYPE html> <html> <head> <title>window_load.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> this is my HTML page.<br> </body> <script type="text/javascript"> /** *把页面中的所有的数据加载完以后触发该方法 **/ window.onload = function(){ alert("ssssss"); } </script> </html>

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

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等操作系统。

用户登录
用户注册