首页 文章 精选 留言 我的

精选列表

搜索[笔记工具],共10000篇文章
优秀的个人博客,低调大师

JavaScript DOM学习笔记--创建追加元素

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>动态添加城市</title> <script> window.onload = function(){ document.getElementById("btn").onclick = function(){ //1.获取ul元素节点 var ulEle = document.getElementById("ul1"); //2.创建城市文本节点 var textNode = document.createTextNode("深圳");//深圳 //3.创建li元素节点 var liEle = document.createElement("li");//<li></li> //4.将城市文本节点添加到li元素节点中去 liEle.appendChild(textNode);//<li>深圳</li> //5.将li添加到ul中去 ulEle.appendChild(liEle); } } </script> </head> <body> <input type="button" value="添加新城市" id="btn"/> <ul id="ul1"> <li>北京</li> <li>上海</li> <li>广州</li> </ul> </body> </html>

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

【Android学习笔记】Android Studio简单断点调试

首先点击断点调试按钮运行App 启动之后,会弹出如下图的提示框,不要管,几秒之后这个弹框会自动消失,然后App会成功运行。 下面介绍一下断点调试的相关操作按钮对应的功能: 按钮1的功能:从当前断点跳到下一个断点,如果当前断点为最后一个断点则点击后断点结束,App正常运行。 按钮2(step over)的功能:一步步往下走,及按代码逻辑一行一行代码往下走。 按钮3(step into)的功能:遇到方法就往方法里走。 按钮4(force step into )的功能:所有方法看完整,即可以看到你所调用的所有方法的实现会让你跟着它走一遍。 按钮5(step out )的功能:有断点下一个,走完断点继续走,断点走完之后会一直往下跳,无法结束断点而让App正常运行。 按钮6(run to Cursor)的功能:下个断点我们见,同按钮1的功能。 按钮7的功能:停止App的运行。

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

java学习笔记--反射( 后期学习补充用法)

可以先参考下大佬的: 大佬1 大佬2 类字节码文件是在硬盘上存储的,是一个个的.class文件。我们在new一个对象时,JVM会先把字节码文件的信息读出来放到内存中,第二次用时,就不用在加载了,而是直接使用之前缓存的这个字节码信息。 字节码的信息包括:类名、声明的方法、声明的字段等信息。在Java中“万物皆对象”,这些信息当然也需要封装一个对象,这就是Class类、Method类、Field类。 通过Class类、Method类、Field类等等类可以得到这个类型的一些信息,甚至可以不用new关键字就创建一个实例,可以执行一个对象中的方法,设置或获取字段的值,这就是反射技术。 方法区存的是类的信息,不是存类对象的,类加载器加载类是通过方法区上类的信息在堆上创建一个类的Class对象,这个Class对象是唯一的,由JVM保证唯一,之后对这个类的创建都是根据这个Class对象来操作的 反射是什么呢?当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻,举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName(“com.java.dbtest.TestConnection”);通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。 Java 反射机制主要提供了以下功能 在运行时判断任意一个对象所属的类。 在运行时构造任意一个类的对象。 在运行时判断任意一个类所具有的成员变量和方法。 在运行时调用任意一个对象的方法 今天回过头来找了点视频来简单了解下了反射机制 以下纯属个人学习总结 如有问题 欢迎讨论 一起进步 问:*有人会问 反射到底是用来干什么的?* 答:目前学了感觉是没啥用 但是到了框架部分 就大有用处 就好比框架是个房子 里面的构造都已经给你搭建好了 你想要对其中的部分进行修改添加 这个时候就需要反射来动态修改了 主要的方法都在java.lang.reflect中 reflect是反射的英文 不知道这么说 是不是可以理解 因为我也没学到过框架 只是照葫芦画瓢在这瞎几把乱说 如有问题 请指出。 Class.forName是在bin层次下 new FileReader是在项目层次下 下面会用到 先简要了解下 反射(类的加载概述和加载时机) 类的加载概述 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。 加载 就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。 连接 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用 初始化 加载时机 创建类的实例 访问类的静态变量,或者为静态变量赋值 调用类的静态方法 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象 初始化某个类的子类 直接使用java.exe命令来运行某个主类 反射(类加载器的概述和分类) :类加载器的概述 负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。 :类加载器的分类 Bootstrap ClassLoader 根类加载器 Extension ClassLoader 扩展类加载器 Sysetm ClassLoader 系统类加载器 :类加载器的作用 Bootstrap ClassLoader 根类加载器 也被称为引导类加载器,负责Java核心类的加载 比如System,String等。在JDK中JRE的lib目录下rt.jar文件中 Extension ClassLoader 扩展类加载器 负责JRE的扩展目录中jar包的加载。 在JDK中JRE的lib目录下ext目录 Sysetm ClassLoader 系统类加载器 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径 反射(反射概述) :反射概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 要想解剖一个类,必须先要获取到该类的字节码文件对象。 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。 :三种方式 a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件 b:静态属性class,锁对象 c:Class类中静态方法forName(),读取配置文件 举一个栗子: package fuxi; class Person{ } public class One { public static void main(String args[]) throws ClassNotFoundException { Person person=new Person(); Class clazz1=person.getClass(); //根据实体类得到class字节码 Class clazz2=Person.class; //静态属性class加载 Class clazz3=Class.forName("fuxi.Person");//路径要写全 java文件中的得到字节码 System.out.println(clazz1.equals(clazz2)); System.out.println(clazz1.equals(clazz3)); System.out.println(clazz2.equals(clazz3)); } } 输出: true true true 意思就是三个得到的字节码class都是同一个 用反射和配置文件解决问题: package fuxi; import java.io.BufferedReader; import java.io.FileReader; interface Animal{ void run(); } class Dog implements Animal{ @Override public void run() { System.out.print("汪汪汪"); } } class Cat implements Animal{ @Override public void run() { System.out.print("喵喵喵"); } } class Ox{ public void run(Animal animal) { animal.run(); } } public class One { public static void main(String args[]) throws Exception { BufferedReader br = new BufferedReader(new FileReader("Animal.properties")); String name=br.readLine(); System.out.println(name); Class clazz=Class.forName(name); Ox animal=new Ox(); animal.run((Animal) clazz.newInstance()); } } 还有在项目下创建一个配置文件 内容是: fuxi.Dog 如果是原来的多态 写死了 那么每次都要修改源文件 而用反射的话 就可以的动态记载配置文件里面的内容 只要修改配置文件就行 降低了耦合度 通过反射获得构造函数并使用 Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor 举个栗子: package fuxi; class Person { String name="xx"; int age=3; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { name="xx"; age=3; } @Override public String toString() { return name + " " + age; } } public class One { public static void main(String args[]) throws Exception { Class clazz = Class.forName("fuxi.Person"); Person person = (Person) clazz.newInstance(); System.out.print(person); } } 输出: xx 3 这个时候有无参的构造函数 所以可以 如果去掉这个无参的构造函数 那么就会报错 这个时候就得Class类的getConstructor获取class类的构造函数 package fuxi; import java.lang.reflect.Constructor; class Person { String name="xx"; int age=3; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { name="xx"; age=3; } @Override public String toString() { return name + " " + age; } } public class One { public static void main(String args[]) throws Exception { Class clazz = Class.forName("fuxi.Person"); Constructor[] constructors=clazz.getConstructors();//获得这个类的构造函数数组 System.out.println(constructors[0]); System.out.println(constructors[1]); Constructor constructor=clazz.getConstructor(String.class,int.class);////获取有参构造 System.out.println(constructor); Person person=(Person) constructor.newInstance("xiaoming",1);//通过有参构造创建对象 System.out.print(person); } } 输出: public fuxi.Person(java.lang.String,int) public fuxi.Person() public fuxi.Person(java.lang.String,int) xiaoming 1 通过反射获取成员变量并使用 Field * Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField(“name”)方法获取,通过set(obj, “李四”)方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值 package fuxi; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; class Person { public String name="小明"; public int age=3; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { name="xx"; age=3; } @Override public String toString() { return name + " " + age; } } public class One { public static void main(String args[]) throws Exception { Class clazz = Class.forName("fuxi.Person"); Field[] fields=clazz.getFields(); //获取类属性的全部属性 前提的public 如果是包内访问和private都不行 System.out.println(fields[0]); System.out.println(fields[1]); Person person=(Person) clazz.newInstance(); //通过无参构造创建对象 //Field field=clazz.getField("name"); //获取姓名字段 //field.set(person, "小张"); //修改姓名的值 Field field=clazz.getDeclaredField("name"); //暴力反射获取字段 field.setAccessible(true); //去掉私有权限 field.set(person, "小张"); System.out.print(person); } } 输出: public java.lang.String fuxi.Person.name public int fuxi.Person.age 小张 3 总结: 属性权限如果不是公有的话 1. 要获取属性只能 clazz.getDeclaredField 暴力获取属性 2. 要修改属性只能 setAccessible 去掉权限限制 这么看来反射是不是很强盗 ? 也说明了他的无敌 通过反射获取方法并使用 * Method * Class.getMethod(String, Class…) 和 Class.getDeclaredMethod(String, Class…)方法可以获取类中的指定方法,调用invoke(Object, Object…)可以调用该方法 package fuxi; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import javax.print.attribute.standard.Media; class Person{ String name; int age; public Person(String name,int age) { this.name=name; this.age=age; } public void printf() { System.out.println(name); } public void printf(int age) { System.out.println(name+" "+age); } } public class One { public static void main(String args[]) throws Exception { Class clazz=Class.forName("fuxi.Person"); Constructor constructor=clazz.getConstructor(String.class,int.class); Person person=(Person) constructor.newInstance("小明",10); Method method1=clazz.getMethod("printf"); method1.invoke(person); Method method2=clazz.getMethod("printf", int.class); method2.invoke(person, 11); } } 输出: 小明 小明 11 或许你们会有个疑惑 为什么clazz.getMethod(“printf”, int.class)? 其实这一部分还属于反射部分 还是字节码的部分 所以得传入class形式 最后invoke的时候才是具体的值 泛型反射: 这个之前学泛型的时候提到过 现在简单回顾一下 泛型检查是在编译器 运行时 class文件中类型都被泛型擦除为Object 这个时候我们可以通过泛型反射 往ArrayList<Integer>中 添加String类型 package fuxi; import java.lang.reflect.Method; import java.util.ArrayList; public class One { public static void main(String args[]) throws Exception { ArrayList<Integer> arrayList=new ArrayList<Integer>(); arrayList.add(1); arrayList.add(2); Class clazz=Class.forName("java.util.ArrayList"); Method method=clazz.getMethod("add", Object.class); method.invoke(arrayList, "adb"); System.out.print(arrayList); } } 输出: [1, 2, adb] 通过反射写一个通用的设置某个对象的某个属性为指定的值 package fuxi; import java.lang.reflect.Field; class Person{ String name; int age; public Person(String name,int age) { this.name=name; this.age=age; } } public class One { public static void main(String args[]) throws Exception { Person person=new Person("小明", 10); tool(person, "name", "小王"); System.out.print(person.name); } public static void tool(Object person,String name,Object object) throws Exception { Class clazz=Class.forName("fuxi.Person"); Field field=clazz.getDeclaredField(name); field.setAccessible(true); field.set(person, object); } } 输出: 小王 总结: 1. Class.forName可以读取一个类的字节码文件即Class文件 Class可以通过newInstance()创建一个实体类 通过反射获取带参构造方法并使用 Constructor Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance(“张三”,20)方法创建对象 通过反射获取成员变量并使用 Field Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField(“name”)方法获取,通过set(obj, “李四”)方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值 通过反射获取方法并使用 Method Class.getMethod(String, Class…) 和 Class.getDeclaredMethod(String, Class…)方法可以获取类中的指定方法,调用invoke(Object, Object…)可以调用该方法,Class.getMethod(“eat”) invoke(obj) Class.getMethod(“eat”,int.class) invoke(obj,10) 通过反射越过泛型检查 动态代理 最后再来讲一下 动态代理: 代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象。 代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。 所以说动态代理其实就是通过反射来生成一个代理 优点: 可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。 但是只能针对接口进行动态代理 所以 你要代理的类只能继承接口而不是一个类 在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。 重要:InvocationHandler接口 在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口 作为调用处理器”拦截“对代理类方法的调用 当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑 最终会调用InvocationHandler的方法 InvocationHandler Object invoke(Object proxy,Method method,Object[] args) //意思 :调用处理器 Java动态代理其实内部也是通过Java反射机制来实现的,即已知的一个对象,然后在运行时动态调用其方法,这样在调用前后作一些相应的处理,这样说的比较笼统 接口: package Father; public interface FatherInter { public void login(); public void submit(); } 继承接口实现类: public class Son implements FatherInter { @Override public void login() { System.out.println("登录"); } @Override public void submit() { System.out.println("提交"); } } 调用处理器: public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); method.invoke(target, args); //执行被代理target对象的方法 System.out.println("日志记录"); return null; } } Main函数: public class Main { public static void main(String[] args) { Son si = new Son(); si.login(); si.submit(); System.out.println("-------------------------------"); MyInvocationHandler m = new MyInvocationHandler(si); FatherInter s = (FatherInter)Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m); //Proxy提供用于创建动态代理类和实例的静态方法 //newProxyInstance返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。 s.login(); s.submit(); } } 输出: 登录 提交 ------------------------------- 权限校验 登录 日志记录 权限校验 提交 日志记录 总结: 1. 动态代理 被代理的类要继承接口才行 基类不行 2. 写一个类继承InvocationHandler 作为中间层 给它传入你的实现类 额外添加的代码写在里面的invoke方法中 3. class类的getInterfaces()方法返回的是 实现接口数组 4. Proxy.newProxyInstance返回的是接口 而不是实现类 遇到这么一个问题 5. invoke(Object proxy, Method method, Object[] args) proxy其实没有啥用 method是为了method.invoke(target, args)执行被代理类的方法args则是被调用方法的参数 6. Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象 Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m);中getClassLoader()和getInterfaces()是不必动的 固定死了 代表加载器和实现类实现的接口 m是调用处理器:InvocationHandler的实现类 Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to Father.FatherInter at Father.Main.main(Main.java:13) 代理类没有实现接口,而是实现了某一基类。大家要注意了哦。 参考: 代理类: https://blog.csdn.net/andyzhaojianhui/article/details/72833114

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

java学习笔记--枚举类(综合网络用法)

什么是枚举类? 个人理解就是一个 定义了一个规范 你只能从固定的一些值中取值,限定了范围 比如性别,四季就可以用枚举类 而且是类型安全的 意思就是 你不能传入int之类的其他变量给枚举类 枚举类可以定义在一个类里 也可以单独定义 使用enum关键字 枚举类的定义格式: enum 类名{ //枚举值 } 枚举要注意的细节: 1. 枚举类也是一个特殊的类。 2. 枚举值默认的修饰符是public static final。 3. 枚举值就是是枚举值所属的类的类型, 然后枚举值是指向了本类的对象的。 4. 枚举类的构造方法默认的修饰符是private的。 5. 枚举类可以定义自己的成员变量与成员函数。 6. 枚举类可以自定义构造函数,但是构造函数的修饰符必须是private。 7. 枚举类可以存在抽象 的方法,但是枚举值必须要实现抽象 的方法。 8. 枚举值必须要位于枚举类 的第一个语句。 总的来说 枚举值就是枚举类的实例 可以单独一个枚举值 也可以枚举值绑定一个变量 下面会介绍的 枚举用法一: 常量值 enum Sex{ 男, 女 }//男 女是Sex的实例 分隔符用逗号 如何遍历枚举? for(Sex s : Sex.values()){ System.out.println(Sex.name); //name是枚举值的名字 如上那就是男和女 } 枚举用法二: switch //季节枚举类 enum Season{ spring,summer,autumn,winter; } public eclass Demo8 { public static void main(String[] args) { Season season = Season.summer; switch(season){ case spring: System.out.println("春天..."); break; case summer: System.out.println("夏天..."); break; case autumn: System.out.println("秋天..."); break; case winter: System.out.println("冬天..."); break; } } }//switch里面直接放枚举值 不要加枚举类名字 ———————————————————————————————————————————————————————————————————————————— 枚举用法三:枚举类有方法 枚举值和参数绑定 构造函数是private的 enum Gender{ // public static final Sex man = new Sex("man"); 要重写Gender才行 用来覆盖无参的构造函数 man("男"),woman("女"); String value; //成员 变量 private Gender(String value){ this.value = value; } } ———————————————————————————————————————————————————————————————————————— //**枚举用法四:覆盖枚举的方法** enum Sex{ // public static final Sex man = new Sex("man"); man("男"){//匿名类 @Override public void run() { System.out.println("男人在跑..."); } },woman("女"){ @Override public void run() { System.out.println("女人在跑..."); } }; //枚举值 String value; //成员 变量 public类型的 // public static final Sex man = new Sex(); //构造函数 private Sex(String value){ this.value = value; } //成员函数 public void getValue(){ System.out.println("value :"+ value); } public abstract void run(); } —————————————————————————————————————————————————————————————————————————————— 用法五:实现接口 public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour{ RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } //接口方法 @Override public String getInfo() { return this.name; } //接口方法 @Override public void print() { System.out.println(this.index+":"+this.name); } } —————————————————————————————————————————————————————————————————————————————————————— 用法六:使用接口组织枚举 public interface Food { enum Coffee implements Food{ BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO } enum Dessert implements Food{ FRUIT, CAKE, GELATO } } switch适用的数据类型: byte \ char \short \ int \ String\枚举类型 注意: switch中 case语句后面跟的枚举值,只需要单写枚举值即可,不需要再声明该 枚举值是属于哪个枚举类的。

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

java学习笔记--io流的异常处理

public static void main(String[] args) { // readTest(); copyImage(); } // 拷贝图片 public static void copyImage() { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { // 找到目标文件 File inFile = new File("F:\\美女\\1.jpg"); File outFile = new File("E:\\1.jpg"); // 建立输入输出通道 fileInputStream = new FileInputStream(inFile); fileOutputStream = new FileOutputStream(outFile); // 建立缓冲数组,边读边写 byte[] buf = new byte[1024]; int length = 0; while ((length = fileInputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, length); } } catch (IOException e) { System.out.println("拷贝图片出错..."); throw new RuntimeException(e);//读取的错误 } finally { // 关闭资源 try { if (fileOutputStream != null) { fileOutputStream.close(); System.out.println("关闭输出流对象成功..."); } } catch (IOException e) {//关闭的错误 System.out.println("关闭输出流资源失败..."); throw new RuntimeException(e); } finally { if (fileInputStream != null) { try { fileInputStream.close(); System.out.println("关闭输入流对象成功..."); } catch (IOException e) { System.out.println("关闭输入流对象失败..."); throw new RuntimeException(e); } } } } } 总结:io流抛出异常的位置有两个 1. 打开的文件的时候 文件损坏或者硬盘损坏等 主要是 抛出包装后的错误信息RuntimeException(e) 2. 流关闭放在finally中 但是关闭流的时候也会发生错误 3. 如果io流抛出异常 就无法执行接下里的任务 所以我们要try{} catch(){}finally{}

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

Java小白进阶笔记(5)-进阶面向对象

继续学习:7.偏头痛杨的Java入门教学系列之进阶面向对象篇 上Java课的时候没弄明白接口,今天终于明白了(但没使用过,还停在理论的程度,可能理解也不准确,以后学通了会回来补充:)如果你刚学Java,对Java的三要素不能理解,强烈推荐看一下这篇文章。 下面是看完偏头痛杨的这篇博客的摘要 继承(Inheritance,也称为泛化) 为什么要继承 继承是面向对象编程实现软件复用的重要手段 当子类被继承,子类作为一种特殊的父类,将直接获得父类的属性和方法,同时子类也可以增加自己的属性和方法,以及重新定义父类的属性,重写父类的方法以获得和父类方法实现的不同的功能。 在类层次结构中,,对父类的改动自动反映在它所有的子类,子类的子类中,不需要修改或重新编译任何低层次的类,那些类通过继承而接收父类中新改变的信息,仅仅需要在层次结构中定义行为和属性一次,那么,以后将自动由所有子类所继承。 继承有利于软件的复用,避免重复代码,提高开发效率。 什么时候会用到继承 (这里理解比较浅,以后对Java继承加深理解后再补充) 当两个类具有相同的特征(属性)和行为(方法)时,可以将相同的部分抽取出来放到一个类中作为父类,然后这两个类作为这个父类的子类继承父类的属性和方法。 继承的一些注意事项 子类无法继承父类的构造方法 Java只支持单继承(可以用接口变相实现多继承) 父类中private的属性和方法无法被继承 继承提高了类之间的耦合性 所有的类默认继承java.lang.Object 特别的 实例化子类对象的时候总会在执行子类构造方法之前去调用父类的构造方法(先实例化父类,再实例化子类,如果继承的类很多则可能影响性能) 如果父类中有无参构造,则默认先调用父类的无参构造(子类不用显示的调用super()) 如果父类没有无参构造,则需显示的在子类构造中用super()来调用父类相应的构造,且必须在第一行调用 如果父类中只有有参构造,而子类没有显示的去调用则会报错 如果父类中只有有参构造,而子类显示的去调用父类的无参构造则也会报错 this和super关键字 this()与super()必须定在在构造方法中,并且必须在第一行 super() 调用父类的构造方法,只能出现在子类的构造器中,且必须是第一行。 super()中的参数,决定了调用父类的那个构造方法 如果子类的构造方法中没有出现super,那么编译器默认加上super(),即调用父类的无参构造,如果父类没有无参构造,编译器就会报错。 this() 调用本类的构造方法 注意: this()和super()不能出现在static的方法与static块中(这个不理解,感觉可能与加载顺序有关,以后回来补充) this()调用和super()调用不会同时出现 this. 和super. super.指向父类的引用,我们可以通过super关键字来实现对父类成员的访问。 this.指向本类的引用,我们可以通过this关键字来实现对本类成员的访问。 final关键字 final可以修饰的元素: 类:不能被继承,类被定义成final,那么类中所有的方法全部为final 方法:不能在子类中被覆盖(private方法除外,因为private方法不能被子类继承),即不能修改 变量:被final修饰,也就是常量 包(package) 包主要用来对类和接口进行分类 与文件夹类似,把Java类文件放到不同包(文件夹)中,不同的报下,文件名可以重复 与包相关的语句:1.打包语句package;2.引用包语句import package语句必须写在第一行,不写的话,默认放在默认路径下,也就是src根目录 使用import访问第三方或者其他包中的类,如果这个类与本类在同一个包中则不需要import //package 包名; //package 包名.子包名.子子包名; package com.webi.hwj.weixin.controller; public class WeixinHandleController { } import 包名; import 包名.子包名.子子包名; package com.webi.hwj.weixin.controller; import org.apache.log4j.Logger; public class WeixinHandleController { Logger logger = Logger.getLogger(WeixinHandleController.class); } 封装 将对象实现的细节(属性和方法)隐藏起来,然后通过一些公用方法来暴露该对象的功能。 为什么要封装 开发者让使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作。 如何实现封装 Java的访问控制符从小到大:private,default,protected,public范围:同一类,同一包,子类,全局范围(同一项目) 注意 类的控制级别只有public和default,成员变量与方法四个都有 如果类的构造方法为private,则其他类均不能生成该类的实例(自己类内部可以) Java类中一般会使用private来修饰成员变量,来防止外部调用 模块设计追求高内聚、低耦合。 高内聚:尽可能把模块的内部数据、功能实现细节隐藏在模块的内部独立完成,不允许外部直接干涉。低耦合:仅暴露少量的方法给外部使用。 方法的覆盖 重写(overriding) 在父子类继承情况下,子类写出一个跟父类一摸一样的方法,方法体内可以修改,这就是重写。优势:子类可以根据需要,定义特定与自己的行为,即子类可以根据需要实现父类的方法注意:子类中写的要覆盖父类的方法的访问权限要不小于父类中被覆盖方法的访问权限 重载(overloading) 在同一个类中,新写一个方法,方法名跟某一个老方法一样,但参数必须不一样,返回值可能也不一样,这就是新方法重载了老方法。比较常见的重载方式是重载构造方法 多态(Polymorphism) 多态是建立在继承的基础上的,是指子类类型的对象可以赋值给父类类型的引用变量,但运行时仍表现子类的行为特征。也就是说,同一中类型的对象执行同一个方法时可以表现出不同的行为特征。 为什么要使用多态 可以增强程序的可扩展性及可维护性,使代码更加简洁。作用:在方法传递引用数据类型的时候,使方法内部的代码更具有可维护性,当有新增子类时,方法内部的代码不用去修改,进一步的使用抽象的概念。 java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定,如果编译时类型与运行时类型不一致,就可能会出现所谓的多态。 多态的三个必要条件: 要有类继承或实现接口 要有方法重写 父类引用指向子类对象(或接口引用指向实现类对象)。 满足条件后,当调用父类中被重写的方法后,运行时创建的是哪个子类的对象,就调用该子类中重写的那个方法。 注意 在多态情况下,父类的成员变量无法被子类覆盖,因此需要使用setter/getter方法。 在继承情况下,父类的成员变量可以被子类覆盖。 在多态情况下,子类有重写父类方法的情况,则调用子类方法。 多态情况下,对象无法调用子类独有的方法与属性,只能调用编译类型的成员。 抽象类、抽象方法 抽象方法 可以只有方法定义,没有方法实现的方法,抽象方法由子类来实现。子类必须实现父类的抽象方法,否则报错,但如果子类也是抽象类就没问题了 抽象类 抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。 注意: 抽象类不能实例化,即不能new,抽象类的构造方法不能用于创建实例,而是用于被子类调用。可以这么理解:抽象类,既然还是抽象类,那怎么能实例化呢?比如说你跟老板说买十斤“鱼”,这个老板就为难了,“鱼”是一个抽象的概念,应该说清楚,买鲤鱼还是鲢鱼(也就是被子类调用)。 static、final、private方法与构造方法不能被声明为抽象方法 抽象类中可以有非抽象方法,但含有抽象类的方法一定是抽象方法。 抽象类允许有构造方法(不是抽象方法),在子类实例化对象时会自动调用父类的构造方法 接口 接口是抽象类的变体,在接口中,所有方法都是抽象的,多继承性可通过实现这样的接口而获得。接口就是标准(一些类需要遵守的规范),是用来隔离具体实现的(或者说是和具体实现解耦)。 程序接口的使用就将调用者和提供者之间进行了解耦,只要实现者遵守这个接口来做实现就好,实现细节不用管。比如说U盘,不需要关注U盘里存放的内容与不同电脑的兼容性,只要USB接口一样就OK。 注意 接口不是类,不能被实例化也没有构造方法,但抽象类有构造方法。 接口内所有的属性均默认为public static final,只能在定义时指定默认值。 接口内所有的方法均默认为public abstract,不能用static&final。 接口内不允许有正常方法(带方法体的方法)。 接口可以同时继承多个父接口,但接口只能继承接口,不能继承类。 方法提供者与方法调用者有可能是一个人也可能是不同的人(可以理解成,写一个接口,可以被自己调用也可以被别人调用)。 一个java源文件中最多只能有一个public接口,并且文件名与接口名相同。 类实现接口(implements) 类一旦实现接口,就必须实现其所有方法,否则这个类必须声明为抽象类。一个类可以只能继承一个类,但可以实现多个接口。多个无关的类可以实现一个接口,一个类可以实现多个无关的接口。一个类可以在继承一个父类的同时,实现一个或多个接口。 接口与抽象类的区别 接口不能含有任何非抽象方法,而抽象类可以。(JDK8以及以上除外) 类可以实现多个接口,但只能继承一个父类。 接口不是类分级结构的一部分,没有联系的类可以实现相同的接口。(这也是接口的优势之一) 更多的请看原博客,这里简单的摘了一些。以便以后快速拾起来。

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

Java小白进阶笔记(3)-初级面向对象

继续学习:4.偏头痛杨的Java入门教学系列之初级面向对象篇 分割线中为原文的摘录: 面向过程编程&面向对象编程 从面向过程到面向对象,不仅仅是编程方式的改变,更重要的是思维方式的改变。 面向过程编程 按照顺序执行的一系列指令,通常是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,最后一个一个依次调用函数来解决。 面向对象编程 从不同的角度来看待计算机程序,它注重的是计算机所完成的任务,而非处理方式。从现实世界中客观存在的事物出发来构造软件系统,并在系统构造中尽可能运用人类的自然思维方式来思考问题,把问题中的事物分解为为系统中的对象,给对象赋予相应的属性和行为,通过多个对象的相互协调来解决问题,对象是系统的基本构成单位。 传统的C语言属于面向过程编程,Java语言属于面向对象编程。 ATM取款机程序的例子 面向过程编程: 输入密码,系统判断是否正确,如正确,进入取款界面,如错误,提示重新输入。 进入取款界面,输入取款金额,系统判断余额是否足够,如不足,提示;如足够,点钞。 吐出钞票,打印票据。 面向对象编程:根据要解决的问题,可以抽象出如下对象:客户、银行卡、现金、票据等。这些对象没有先后顺序,共同作用才构成了整个系统。我们只要用代码设计出这几个类型的对象,然后让他们互相通信、传递消息就可以完成系统功能。 猪八戒吃西瓜的例子 面向过程编程:吃(猪八戒,西瓜)面向对象编程:猪八戒.吃(西瓜) 作业 创建一个人类,该类需要有定义:名字、体重、年龄三种属性(数据类型分别为:String,int,int),还要定义吃饭、睡觉、打豆豆三种方法。类中需要定义有参构造,需要通过有参构造把类中的三种属性初始化。 三种方法的规则: 吃饭:需要传递参数,并输出"xxx在吃饭" 睡觉:通过前面的有参构造初始化,输出"xxx在睡觉",xxx为名字(对象的属性),方法不用定义形参。 打豆豆: 通过前面的有参构造初始化,需要返回给调用者"xxx的体重是a,年龄是b",并在调用处输出。 注意: xxx、a、b均为动态的,不是写死在代码里的。 输出的写法为:System.out.println("你好哇,这里是作业demo示例哟~~~"); 需要在main方法中实例化三个人类的对象,分别设置与输出三个属性(名字、体重、年龄),并调用三个方法,其中把打豆豆方法的返回值打印出来。 我的解答 ps:Java初学者,如果你是高手就不用看(xiao)了(hua)(ノへ ̄、) package test; public class People { String name; int weight; int age; public People() { } public People(String name,int weight,int age) { this.name=name; this.weight=weight; this.age=age; } public void eat(String food) { System.out.println(name+"is eating"+food+"now !"); } public void sleep() { System.out.println(name+"is sleeping now!"); } public String hitdoudou() { return name+"的体重是"+weight+",年龄是"+age; } } package test; public class Test { public static void main(String[] args) { People p1 = new People("Jack",152,21); p1.eat("apple"); p1.sleep(); String hit = p1.hitdoudou(); System.out.println(hit); } } 输出结果: Jackis eatingapplenow ! Jackis sleeping now! Jack的体重是152,年龄是21

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

Jenkins Linux下安装、配置(学习笔记一)

1、安装JDK、Jenkins yum install java-1.8.0-openjdk.x86_64 -y sudo wget -O /etc/yum.repos.d/jenkins.repohttp://pkg.jenkins-ci.org/redhat/jenkins.repo sudo rpm --importhttps://jenkins-ci.org/redhat/jenkins-ci.org.key sudo yum install jenkins -y sudo service jenkins start sudo chkconfig jenkins on 2、关闭防火墙 firewall-cmd --permanent --new-service=jenkins firewall-cmd --permanent --service=jenkins --set-short="Jenkins Service Ports" firewall-cmd --permanent --service=jenkins --set-description="Jenkins service firewalld port exceptions" firewall-cmd --permanent --service=jenkins --add-port=8080/tcp firewall-cmd --permanent --add-service=jenkins firewall-cmd --zone=public--add-service=http --permanent firewall-cmd --reload 3、浏览器输入http://ip:8080 4、获取密码:cat /var/lib/jenkins/secrets/initialAdminPassword xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 5、安装推荐的插件 6、创建用户

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

华文慕课Java程序设计笔记

对象的自动清除 对象回收是由垃圾回收线程负责 System.gc()方法可以要求系统进行垃圾回收,仅仅是建议系统 java没有“析构方法”,但Object的finalize()有类似方法 系统在回收时会自动调用对象的finalize()方法 protected void finalize() throws Throwable{} 子类的finalize方法可以在里面释放系统资源,一般来说,子类的finalize方法中应该调用父类的finalize方法。 内部类与匿名类 内部类 定义在一个类的内部 使用分为内部使用和外部使用 内部类总可以直接访问外部类的字段及放啊 内部类总访问外部类的字段可以用“外部类名.this.字段”的方式 用static修饰内部类,表明该内部类实际是一种外部类 因为它与外部类的实例无关 有人认为static的类是嵌套类,不是内部类 内部类的使用 匿名类 它没有类名,在定义类的同时就生成该对象的一个实例,不取名字,直接用父类或接口的名字 一次性使用的类 例子: new Handler(){ ... } 局部类 同局部变量一样,方法中的内部类 不能用public,private,protected,static修饰 但可以被final,abstract修饰 可以访问器外部类的成员 不能够访问该方法的局部变量,除非是final局部变量。 Lambda表达式 基本写法 (参数) -> 结果 例子: (String s) -> s.lenth(); x -> x*x; () -> {System.out.println("aaa")} 大体上相当于其它语言的”匿名函数”或”函数指针” 在java中它实际上是“匿名类的一个实例” 装箱 基本类型的包装类 它将基本类型包装成Object integer i = new Integer(10); Integer i=10; 实际为:Integer i=Integer.valueOf(10); 拆箱 int a=i; 实际为:a=i.intValue(); 枚举 可以在enum定义体中,添加字段,方法,构造方法 image 注解 又称为注记,标记,标记,注释 是在各种语法要素上加上附加信息,以供编译器或其他程序使用 常用注解: @Override 表示覆盖父类的方法 @Deprecated 表示过时的方法 @SuppressWarnings 标识让编译器不产生警告 引用与指针 引用实质就是指针 但是它是受控的,安全的 比如: 会检查空指引 没有指针运算 不能访问没有引用到的内存 自动回收垃圾 (1) 指针 》引用类型,引用本身就相当于指针,可以用来修改对象的属性,调用对象的方法 (2)指针运算 》数组 (3)函数指针 》接口,lambda表达式 (4)指向结点的指针 》对象的引用 (5)使用JNI java Native interface 它允许java代码和其他语言写的代码进行交互 基本类型的相等 基本类型: 数值类型:转换后比较 浮点数,最好不直接用== Double.NAN==Double.NAN结果为false boolean型无法与int比较 注 valueOf() -128到127会有缓存,超过的话就没有缓存了 枚举类型 内部进行了唯一实例化,可以直接判断 引用对象 “==”是直接看两个引用是否一样 如果要判断内容是否一样,则要重写equals方法 如果重写equals方法,则最好重写hashCode方法,因为一般以内容的hashCode作为唯一性标志 [图片上传失败...(image-845e09-1522336106762)] String对象的特殊性 判断对象,一定不要用==,要用equals 但是字符串变量及字符串常量会进行内部化,相同的字符串常量是==的 String对象的特殊性 异常 异常又称为例外,差错 对应着java运行错误处理机制 基本写法: try{ 语句组 }catch(Exception ex){ 异常处理语句组; } java中处理异常 抛出异常 运行时系统在调用栈中查找:从生成异常的方法开始进行回溯,直到找到 捕获异常的代码 异常的分类 Throwable Error:JVM错误 Exception 多异常的处理 子类异常要排在父类异常的前面 finally语句 无论有无异常,都会执行处理语句 受检的异常 Exception分两种 RuntimeException及其子类,可以不明确处理 否则,称为受检的异常,受检的异常,要求明确进行语法处理,要么捕获,要么抛出异常 自定义异常 创建用户自定义异常类 继承自Exception类或某个子Exception类 定义属性和方法,或重载父类的方法 对于异常,不仅要进行捕获处理,有时候还需要将异常进一步传给调用者,一变让调用者也能感受到这种异常,这是可以在catch语句块或finally 语句块中采取以下三种方式: 将当前捕获的异常再次抛出 重新生成一个异常,并抛出 重新生成一个新异常,该异常中包含了当前异常的信息,如throw new Exception (“some message “,e) 断言及程序的调试 断言 assert 表达式 assert 表达式,信息 在调试程序时,如果表达式不为true,则程序会产生异常,并输出相关的错误信息 例 assert hypotenuse(3,4)==5:”算法不正确”; 它起到对程序的检测作用 编译及运行 只有在JDK1.4及以上的版本才可以使用断言 在运行时,要使assert起作用,则在运行时,使用选项(-ea ,即-enableassetions) 如 java -ea - classpath.Assertion 程序的测试及Junit 在编写程序代码的同时,还编写测试代码来判断这些程序是否正确,这个过程称为“测试驱动”的开发过程 在java的测试过程,经常使用Junit框架 测试函数 @Test来标注测试函数 fail(info) :表示信息出错 assertEqauls(arg1,arg2):表示程序要保证两个参数相等 assertNull(arg):表示参数要为null 程序的调试 语法错误(Syntax error):编辑,编译器发现 运行错误(Runtime error):异常处理机制 逻辑错误(Logic error):调式(debug),单元测试(unit test) 程序的调试 在IDE中,项目中点右键,debug as 进入到调试视图(debug perspective) 调试的手段 断点(breakpoint) 跟踪(trace) 监视(watch) 在很有可能有错误的地方设置断点,然后跟踪 java基础类库 java.lang core java.util java.io java.awt java.net java.sql Object类 Object类是所有类的直接或间接父类 让所有的类有了一致性 equals() ==是引用相等,equals是内容相等 如果覆盖equals方法,一般也要覆盖hashcode方法 getClass()方法是final方法,它返回一个对象在运行时所对应的标识 toString返回对象的字符串表示 finalize用于在垃圾收集前清除对象 notify(),notifyAll(),wait()线程相关 System类 System.getProperty(String name)获取特定的系统属性值 线程 进程:一个程序的运行 线程:程序中单个顺序的流控制称为线程 一个进程中可以含有多个线程 一个进程中的多个线程 特点 分享CPU(并发的或以时间片的方式) 共享内存 线程体 — run()方法来实现的 线程启动后,系统就自动调用run()方法 使用 通过继承Thread类 通过向Thread()构造方法传递Runnable对象 可用匿名类实现Runnable或用lambda表达式 线程池封装

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

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

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

用户登录
用户注册