Java篇
一.工具类
- 私有化构造方法
- 所有方法都是静态的
二.循环
- 在循环的开头加个名字: 如loop:while(){........} 这样使用break loop可以跳出loop所指的循环,这样就可以通过给循环命名来跳出指定的循环
三.字符串String
- 直接赋值的字符串存储在堆的串池中,有则复用,无则创造,如String s1=”abc”;
- 用构造方法创建的字符串存储在堆区中,与串池的地址值不同,如String s2=new String(“abc”);
- boolean c=s1.equals(s2); equals可以区分大小写比较字符串是否一样,返回值为布尔类型,而equalsIgnoreCase可以不区分大小写比较字符串,返回值也是布尔类型
- String str=sc.next(); next()用于接受字符串,nextInt()用于接受整数
- char c=字符串变量.charAt(i); charAt可以返回对应传入索引位置的字符
- str.substring(0,3) substring 可以截取字符串片段,传入两个参数时包头不包尾,传入一个参数时可以截取该索引一直到最后,包头又包尾
- str.replace(Str[i],”*”) replace可以把字符串中的某些字符,即传入的第一个参数,全部替换为新的字符,即传入的第二个参数,返回值是一个新的字符串
- toCharArray可以把字符串变成字符数组并返回
字符串容器StringBuilder
1.StringBuilder sb=new StringBuilder();//空参构造一个字符串容器的类
2.StringBuilder拼接字符串的效率比加号更快,因为拼接过程中只针对一个对象,而加号时每拼接一次就出现一个新的字符串对象
3.sb.append(“aaa”); append用于往容器中添加字符串,返回值是StringBuilder类型
4.sb.append(“aaa”).append(....).append(...) //链式编程,由于append的返回值是StringBuilder类型,可以直接当作对象进行下一步的调用,链式编程省去了先创建新对象再把返回值赋给新对象的过程,可以简化代码
5.直接打印StringBuilder类型的变量得到的不是属性值而是地址值
6.sb.reverse();//reverse用于反转容器中的字符串
7.sb.toString();//toString用于把StringBuilder中的属性值转化为String类型并返回
另一种字符串容器StringJoiner
- 定义格式 StringJoiner sj=new StringJoiner(“,”,”[”,”]”);//第一个参数代表间隔符号,第二个参数代表开始符号,第三个参数代表结束符号
- 与StringBuilder不同,添加用add,且只能添加字符串
- toString可以把容器中的值以字符串类型返回
四.集合的一种:ArrayList
- 定义格式 ArrayList<String> al=new ArrayList<>();//尖括号里的代表泛型,表示在结合里只能存储这一类元素,整型的泛型表示为Integer,字符的泛型为Character,其他的为首字母大写
- al.add(“aaa”);//add用于添加元素,这里与StringJoiner相同
- al.remove(0);//remove删除 把该索引的元素删除,后面的元素自动向前补充,删除成功返回true
- al.get(0);//get查询 把该索引位置的元素返回
- al.set(0,“aaa”);//set修改 把左边索引位置的元素修改为右边传入的参数
五.static关键字
1.被static 修饰的变量可以直接用类名或接口名调用,不用先创建新对象再进行调用
2.被static修饰的变量是随着类加载而加载的,且在堆中用static修饰的变量是单独在一块区域中存储,方便互通
3.静态方法只能访问静态变量,要访问非静态变量只能创建新对象(即静态与静态互通)
六.final关键字
1.final修饰的变量为常量不可被修改
2.final修饰的类为最终类不可被继承
3.final修饰的方法为最终方法不可被重写
七.多态调用成员特点
父类 变量名=new 子类
1.变量调用,编译看左运行看左(从父类中找成员变量,找不到就编译出错,打印的也是父类中成员方法的值)
2.方法调用,编译看左,运行看右
如果运行的是子类特有的方法,那么多态调用的方法就会编译出错
所以一般要有方法的重写
3.多态的弊端:不能访问子类的特有功能
用多态创建的对象不能引用子类的特有方法
八.继承extends
1.只有能存入虚方法表中的方法才能够被继承,也就是父类中没有被private final static修饰的方法才能被子类继承。
2.子类中方法的重写上一行要加上@Override以便于确保重写的正确性
3.在java中所有类都默认继承于object类
九.this,super关键字
1.this关键字先从本类中找,找不到再从父类中找
2.super关键字直接从父类中找
3.super();//可以调用父类的构造方法,空括号里可以传参数,具体要看父类中的构造方法是怎么写的
对于该用法的解释:当子类继承父类时,父类所有的成员变量子类都会有,那么父类的构造方法就适用于子类,所以子类不用将父类的构造方法照搬,可以直接在构造方法的中括号中写一个super();对他的父类进行构造,父类的成员变量被赋值后(如果有带参构造的情况下)子类的成员变量也对应的改变,这样就相当于对子类进行了构造,这样处理可以简化代码
4.this();//可以调用本类中的其他构造方法
十.权限修饰符
1.作用范围private<啥都不写<protected<public
2.Private 只能在本类中使用
3.啥都不写,可以在本类或同一包中的其他类调用
4.Protected多了在其他包中的子类中调用,但是其他包中的无关类(没有继承关系)无法调用
5.Public可以在以上提到的所有地方调用
十一.代码块
1.构造代码块{} 优先于构造方法执行
所以构造方法中的共性代码可以提到上面单独用中括号包裹,形成构造代码块
2.静态代码块static{} 随着类的加载而加载,且只执行一次,方便用于类中数据的初始化以及准备工作,效率高。
十二.抽象类和抽象方法abstract
- 子类中的共性方法可以在父类中定义为抽象方法,强制让子类重写
- 抽象方法所在的类必须是抽象类
- public abstract 返回值类型 方法名(参数列表; 抽象方法定义格式
- public abstract class 类名{} 抽象类定义格式
- 继承抽象类要么重写所有抽象方法要么子类是抽象类
- 抽象类不能被创建对象
十三.接口interface
- 当个别子类有特有共性方法时,就可以将该方法放入接口中
- 接口的定义 public interface 接口名{}
- 接口中的方法要写成抽象方法(接口中的方法默认为抽象方法),当子类调用接口时,强制子类对接口中的方法进行重写
- 调用接口时 类名 implements 接口名{} 也可以先继承在加接口
- 一个类可以调用多个接口
- 接口中没有构造方法
- 接口中的成员变量只能是常量,默认由public static final 修饰
- 与类之间的继承关系不同,一个接口可以继承多个接口,当一个类实现最下面的子接口时,要重写该接口的继承体系中的所有抽象方法
- JDK8后,允许在接口中定义默认方法,需要用default修饰
- 接口中默认方法的定义格式,public default void show(){}
- 默认方法不是抽象方法,不强制被重写,如果被重写要去掉default关键字
- 默认方法的public可以省略,default不能省略
- 如果实现了多个接口,且多个接口中存在相同名字的默认方法,则子类必须对该方法进行重写(这是因为如果不进行重写,当实现类调用该方法时编译器就不知道执行哪个接口里面的默认方法,重写后,将多个重名的默认方法同一为一个方法,这样再进行调用就不会被报错了)
- 接口中的静态方法(被static修饰)不能被重写,且只能通过接口名直接调用,不能通过实现类名或对象名调用(只有进入虚方法表中的方法在子类中需要进行重写,被static修饰的方法不会进入虚方法表,所以不能被重写)
- 关于接口的多态 当一个方法所需要传入的参数类型是接口类型时,那么只要实现了这一接口的类的对象都可以被传入该方法
- 关于适配器设计模式
当实现类只想要重写接口中的某个或某些方法时,由于接口的自身属性,如果直接实现该接口,实现类必须重写接口中的所有方法,这时就可以创建一个中间类xxxAdapter实现接口,对接口中的方法进行空实现,然后再创建实现类继承中间类,这样在实现类中就可以对指定的方法进行重写。此外为了避免中间类被创建对象,中间类要用abstract修饰(抽象类无法创建对象)
十四.内部类
- 内部类可以直接访问外部类的成员变量,包括私有
- 外部类要访问内部类的成员,必须先创建对象
成员内部类
- 成员内部类定义在成员位置,相当于一个成员变量
- 获取成员内部类对象的方法
第一种:当成员内部类被private修饰时,外部类编写方法,对外提供内部类对象 即返回一个new Inner()
第二种:直接创建
假设外部类名Outer内部类名Inner
Outer.Inner oi=new Outer().new Inner();
3.当外部成员变量与内部成员变量重名时,在内部类中如何访问
假设外部类为Outer
则Outer.this.变量名
4.创建内部类的对象时,变量的地址值指向的是内部类,而内部类默认含有一个成员变量存储着外部类的地址值
静态内部类static class
- 静态内部类也是成员内部类的一种
- 创建静态内部类对象的格式:外部类名.内部类名 对象名=new 外部类名.内部类名();
由于被static修饰,所以就不用先创建外部类对象再调用,直接用外部类名调用
- 调用静态内部类中非静态方法的格式:先创建对象,再用对象调用
- 调用静态内部类中静态方法的格式:外部类名.内部类名.方法名();
- 静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问外部类非静态的,需要先创建外部类对象再进行调用
局部内部类(了解即可)
- 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量
- 外界是无法是直接使用局部内部类,需要在方法内部创建对象并使用
- 该类可以直接访问外部类的成员,也可以访问方法捏的局部变量
匿名内部类
- 匿名内部类就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置
- 匿名内部类的格式
new 类名/接口名 ( ) { 方法的重写 };
写类名就相当于该类继承这个类,写接口名就相当于该类实现这个接口
3.匿名内部类的整体就是一个类的子类或一个接口的实现对象,只有中括号中的部分才是类的主体
4.使用场景
当方法的参数是接口或类时,以接口为例,可以传递这个接口的实现类对象(接口的多态)
但是如果实现类只用一次,创建新对象的过程就稍显麻烦,就可以用匿名内部类简化代码,即把匿名内部类这个整天当作参数传入方法中(这里用到了子类的多态以及接口的多态)
十五.项目的搭建
窗口JFrame
- JFrame可以创建一个窗体,是java自带的一个javaBean类
gameJframe.setSize(200,200); setSize方法可以设置窗体的宽和高,单位是像素
- gameJframe.setVisible(true);//界面默认是隐藏的,用setVisible方法传入true可以让窗体可视化,传入false可以隐藏
- .setTitle(“.........”);//方法可以设置界面的标题,即左上方显示的文字
- .setAlwaysOnTop(true);//可以设置界面置顶
- .setLocationRelative(null);//可以设置页面居中
- .setDefaultCloseOperation();//可以设置关闭模式,
传入0时不管点什么都不能结束运行,
1是默认的关闭模式,
2代表只有关闭了所有的页面,虚拟机才会停止运行(所有的窗口都要设置成2才能实现这一效果)
3代表只要关闭一个界面,虚拟机就会停止运行,(这种情况比较适用于该程序最多只有一个界面同时运行时)
- .setLayout(null);//可以取消组件(即窗体内部显示的图片等信息)默认的居中放置,只有取消了才会按照xy轴的方式加载组件
- JButton是一个按钮类,创建一个JButton对象可以在界面内添加一个按钮,再对按钮对象进行鼠标监听,就可实现对按钮的操作
.setBounds();//可以设置按钮对象的坐标以及宽和高
菜单JMenuBar
- 菜单下面对应的是功能选项JMenu,即菜单中的按键
- 功能选项下面对应的是条目JMenuItem,即点击选项展开的内容
- .add();//可以把条目对象添加到功能选项对象中,也可以把功能选项添加到菜单对象中
- 把所有的条目对象和功能选项都添加好后,还要把菜单添加到界面中
要用.setJMenuBar();//给整个界面设置菜单
管理容器JLabel(所有的组件如照片都要放到管理容器中)
- 对于所有的组件,要先添加到管理容器中,再把管理容器添加到界面当中,才能把添加的组件在界面中显示出来
- 对于图片对象 ImageIcon是应用图片组件的一种类
可以通过ImageIcon icon=new ImageIcon(图片文件的路径);来添加图片组件
绝对路径:从盘符开始
相对路径:从非盘符开始,相对于项目的路径
用相对路径的程序兼容性更好,这是因为绝对路径只是在编写代码的电脑上的路径,不一定适用于别人的电脑
- 把ImageIcon对象添加到JLabel对象中后,可以对JLabel对象进行.setBounds(100,200,100,100);//设置图片的位置,单位都是像素,前两个参数代表图片左上点相对于窗体左上角的坐标,后两个代表图片的宽和高
- 把管理容器添加到界面当中
this.getContentPane()//可以获取到窗体,由于窗体是一个隐藏的容器,要先获取,再.add();
把管理容器添加到窗体中,可以写成this.getContentPane().add();
- .setBorder(new BevelBorder(0));//可以给窗体中的图片添加边框,传入0表示让图片凸起来,传入1表示让图片凹进去
- 在窗体中,先添加的图片在最上上方
菜单JMenuBar
- 事件源包括:按钮 图片 窗体,即能发生事件的一些对象
- 事件代表某些操作,如鼠标单击,鼠标划入划出,键盘按下释放等
- 绑定监听:当事件源上发生了某个事件,则执行某段代码
常见的监听有
键盘监听KeyListener
鼠标监听MouseListener
动作监听ActionListener
以上这些监听都是接口,可以让窗口类实现该接口然后就可以在类里面对方法进行重写
十六.爬虫
- 爬虫可以按照一定规则爬取文本中的符合规则的信息
- 第一步创建正则表达式对象:Pattern p=Pattern.compile(“传入的正则表达式”);
- 第二步创建文本匹配器,也就是执行爬取的对象
Matcher m=p.matcher(str);
意思是m这个文本匹配器可以按照p规则爬取str中的内容
- 第三步,m.find(); 让文本匹配器开始进行爬取,若找到符合条件的子串则返回true并在底层记录子串的起始索引和结尾索引+1,并根据subString进行字符串截取
- 第四步,m.group(); //该方法可以把截取的片段进行返回
十七.克隆
- clone是object类中的一个方法
Student s2=s1.clone();
2.克隆的实现,要先让对象类实现Cloneable接口,并且重写clone方法
3.浅克隆:把成员变量中基本数据类型的属性值传给克隆对象
引用数据类型则把地址值传给克隆对象
4.深克隆:同样把成员变量中基本数据类型的属性值传给克隆对象
但引用数据类型会先new一个出来,再把原来的值赋给new出来的引用数据
十八.Lambda表达式
- Lambda表达式的使用前提:必须是接口的匿名内部类,且接口中只能有一个抽象方法
- Lambda的好处:简化函数式接口的匿名内部类的写法
- 格式: ()->{ }
十九.Collection的遍历(第一种:迭代器)
- Collection是java中所有单列集合的顶层接口,分为List和Set两大系列
- List与数组类似,有顺序有索引,Set与链表类似,无顺序,无索引
- 迭代器 Iterator 相当于C语言中的指针遍历链表
- 为集合创建迭代器对象 lterator<泛型> it=集合名.iterator();
创建好迭代器对象后,指针默认指向集合的第一个元素处
- it.hasNext();方法可以判断当前位置是否有元素,如果指向的是null则返回false
- it.next();方法可以获取当前位置的元素并返回,然后将指针向后移动一个单位
- 迭代器是一次性的,当遍历完集合的所有元素后,迭代器的指针不会恢复原位,如果要进行第二次遍历,要创建一个新的迭代器对象
二十.Collection的遍历(第二种:增强for)
- 增强for的底层原理使用迭代器完成的,增强for简化了迭代器代码的书写
- 只有单列的集合和数组才能用增强for遍历
- 格式 for(数据类型 变量名 : 数组或集合名){ }
- 上述括号里左边的变量作为第三方变量接受每次循环遍历到的数据,不会改变原来储存的数据
二十一.Collection的遍历(第三种:Lambda表达式遍历)
- 调用ArrayList中的forEach方法
- 集合名.forEach(s ->System.out.println(s) );
二十二.泛型类,泛型方法,泛型接口
- 泛型的好处是可以在编译阶段规范数据的类型,把运行阶段可能发生的问题提前到了编译阶段,避免了运行阶段因为强制类型转换而可能产生的运行错误
- 当我们不确定形参等数据的类型时,我们就可以定义泛型类,泛型方法,泛型接口
- 泛型中不能写基本数据类型,如int等
- 泛型类的定义方式
修饰符 class 类名<泛型>{ };
- 泛型方法的定义方式,在修饰符后,返回值类型之前加上泛型
修饰符 <E> 返回值类型 方法名 (形参){ };
- 注意:在类名后声明的泛型可以在类中的所有方法使用,而在方法定义中的泛型只能在方法体内使用
- 泛型接口的定义方法
修饰符 接口名<E>{ };
实现带有泛型的接口时,实现类如果没有泛型,则在存入数据时会遵循接口的泛型
而当实现类有泛型时,泛型接口会延续使用实现类的泛型
二十三.泛型的继承和通配符
- 泛型不具有继承性,但是数据具有继承性
比如说:泛型是父类的集合可以往里存子类的数据,但是如果有个方法的形参是一个以父类为泛型的集合,往里传以子类为泛型的集合时就会报错
- ?extend E 表示可以传递E或E的子类
- suoer E 表示可以传递E或E的父类
- 具体使用场景
public static void set (ArrayList<?extend E> list){方法体};
这就代表可以传递以E为泛型的数组或者以E的子类为泛型的数组
- 泛型的通配符的使用可以限制泛型的范围,只要在该类的继承体系内都符合条件时,就可以使用泛型的通配符
二十四.Set集合
- HashSet
基于哈希表,通过比较对象的哈希值(详见下面的数据结构篇对哈希值的解释)储存数据
无顺序,不重复
- LinkedHashSet在HashSet的基础上按照存入顺序在数据之间加了一条新的链表
实现了存入和取出数据的顺序一致
- TreeSet
基于红黑树存储数据,可以设置比较规则,在存入数据的同时实现排序,相较于其他Set集合TreeSet实现了数据的自定义排序
二十五.TreeSet集合(Set的一种)
- TreeSet的特点:可排序,不重复,无索引,底层基于红黑树实现排序,增删查改性能较好
- TreeSet集合集合自定义排序规则的两种方式
①Javabean类实现Comparable接口,指定比较规则
②创建集合时,自定义Comparator比较器对象,指定比较规则
3.比较方法的返回值的特点:
①负数表示当前要添加的元素是小的,存左边
②整数表示要添加的元素是大的,存右边
③0表示添加的元素已经存在,舍弃
二十六.关于Collection的几种集合的应用场景
1.如果想要集合中的元素可重复
用ArrayList集合,基于数组的(用的最多)
2.如果想要集合中的元素可重复,而且当前的增删操作明显多于查询
用LinkedList集合,基于链表的
4.如果想对集合中的元素去重
用HashSet集合,基于哈希表的(用的最多)
5.如果想对集合中的元素去重,而且保证存取顺序
用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet
6.如果想对集合中的元素进行排序
用TreeSet集合,基于红黑树,后续也可以用List集合实现排序