java 面向对象基础学习
前面的忘记写了,算了就不发了
1.单例设计模式 1 2 3 4 5 6 7 8 9 public class test { private static test test = new test (); private test () { } public static test get_object () { return test; } }
在类里面完成这个类的构造,在类外面不能去创建对象,因为对象的构建方法是私有的,只能通过get_object这个类方法去获取这个对象
2.懒汉式单例 在第一次调用的时候创建一个对象,然后在后面的时候都使用这同一个对象
exp
1 2 3 4 5 6 7 8 9 10 public class test { private static test test ; private test () { } public static test getInstance () { if (test==null ){test=new test ();System.out.println("创建对象" );} return test; } }
如果被频繁的使用,用单例,如果用的比较少,就可以用懒汉式单例
3.修饰符
4.继承 所有类都是object的子类
方法重写
构造器 父类和子类都有构造器的情况下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package org.example; import java.io.IOException; import java.util.ArrayList; import java.lang.*; import java.util.Random; import java.util.Scanner; public class Main { public static void main(String[] args){ b ccc=new b(); b cccc=new b("123"); } } class a { public a(){ System.out.println("父类的无参数构造"); } public a(String aa){ System.out.println("父类的有参数构造"); } } class b extends a{ public b(){ System.out.println("子类的无参数构造"); } public b(String aa){ System.out.println("子类的有参数构造"); } }
输出
1 2 3 4 父类的无参数构造 子类的无参数构造 父类的无参数构造 子类的有参数构造
先调用了父类的构造器,然后再次调用子类的构造器
假设父类的构造器只有特定参数的构造器,这样父类内默认没有无参数构造,就只调用子类的构造函数
super 子类的第一行都是super(),无论写不写都有,都会调用父类的构造器
如果父类没有相关参数的构造器,我们就要自己去写一个super去调用父类的构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Main { public static void main (String[] args) { b ccc=new b (); b cccc=new b ("123" ); } } class a { public a (String aa) { System.out.println("父类的有参数构造" ); } } class b extends a { public b () { super ("123" ); System.out.println("子类的无参数构造" ); } public b (String aa) { super ("123" ); System.out.println("子类的有参数构造" ); } }
这里父类是没有无参数构造的
这里使用super方法去调用父类的有参数构造,就不会报错,然后输出如下
1 2 3 4 父类的有参数构造 子类的无参数构造 父类的有参数构造 子类的有参数构造
就近原则 对象调用的时候取决于就近原则
5.多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package org.example;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { a test1 = new b (); a test2 = new c (); test1.run(); test2.run(); } } class a { public void run () { System.out.println("run" ); } } class b extends a { @Override public void run () { System.out.println("run pro max" ); } } class c extends a { @Override public void run () { System.out.println("run ultra" ); } }
都是a,但是在b和c 的状态下,调用的方法也不一样
对于方法,编译看左边,运行看右边
在这里如果给abc都加上成员,再看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package org.example;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { a test1 = new b (); a test2 = new c (); test1.run(); test2.run(); System.out.println(test1.name); System.out.println(test2.name); } } class a { public String name = "a" ; public void run () { System.out.println("run" ); } } class b extends a { public String name = "b" ; @Override public void run () { System.out.println("run pro max" ); } } class c extends a { public String name = "c" ; @Override public void run () { System.out.println("run ultra" ); } }
可以输出两次a
多态强调的是方法和行为的多态
而不是成员变量的,成员变量在开始的时候编译的是谁的就是用谁的
对于变量,编译运行都看左边
多态之后不能调用子类的特有方法,需要用特殊的方法
强制类型转换 如果需要使用子类的特有的方法可以使用强制类型转换去调用这个方法
如果直接这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package org.example;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { a test1 = new b (); test1.stop(); } } class a { public String name = "a" ; public void run () { System.out.println("run" ); } } class b extends a { public String name = "b" ; @Override public void run () { System.out.println("run pro max" ); } public void stop () { System.out.println("stop!" ); } } class c extends a { public String name = "c" ; @Override public void run () { System.out.println("run ultra" ); } }
这样调用会直接报错
但是如果强制类型转换就不会报错
1 2 b test2=(b) test1; test2.stop();
直接转换可能会报错
instanceof 使用instanceof去判断t他的真实类型转换
1 2 3 if( a instanceof b ){ ..... }
6. final 修饰类 类就不能被继承了
修饰方法,方法是最终方法,也不能被重写了
修饰变量,变量只能被修饰一次
1 2 3 final int a = 1 ;a =2 ;
基本类型 的变量是不可以去修改的
引用性的变量不能修改地址但是可以修改地址所指向的值
static final 类似c里面的define 定义一个常量
需要大写加下划线构建
1 public static final String a = "";
程序在编译的时候会直接进行宏替换,与原来的时候是一样的
7.抽象类 关键字 abstract
1 2 3 4 5 public abstract class abstr { public abstract void eat () ; }
不能用来创建对象,需要被继承在之后再子类里面完善
8.模板方法模式 定义一个需要的模板方法
不清楚子类如何去完成,但是知道需要去完成
将需要子类修改的地方定义道抽象方法里面
需要完成的地方就让子类重写完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package org.example;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { b test1 = new b (); c test2 = new c (); test1.hello(); test2.hello(); } } abstract class a { public abstract String run () ; public void hello () { System.out.println("hello" ); System.out.println(run()); } } class b extends a { @Override public String run () { return "b" ; } } class c extends a { @Override public String run () { return "c" ; } }
这里的定义了模板方法hello
然后将实现方法放到子类里面去
这里可以使用final去修饰模板方法,使得方法不能被重写
9.接口
1 2 3 4 5 6 7 8 9 package org.example;public interface A { String SCHOOL_NAME="123" ; void test () ; }
实现类必须要重写相关的函数
接口
1 2 3 4 5 6 7 8 9 10 package org.example;public interface A { String SCHOOL_NAME="123" ; void test () ; }
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package org.example;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { hello y = new hello (); y.test(); } } class hello implements A { @Override public void test () { System.out.println(SCHOOL_NAME); } }
如果实现了多个接口,就需要实现所有的方法
java只能单继承,却可以实现很多的接口,这里就完善了不能单继承的问题
默认方法 jdk8以上的新特点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package org.example;public interface A { String SCHOOL_NAME="123" ; void test () ; default void test2 () { System.out.println("默认方法" ); } }
可以定义默认方法
使用他的实现类去访问
privite方法 jdk版本大于9
1 2 3 private void test2 () { System.out.println("默认方法" ); }
内部类去访问
静态方法 jdk版本大于9
1 2 3 static void test3 () { System.out.println("静态方法" ); }
接口内的方法默认是public的方法
接口多继承 可以将一个接口继承多个和接口
实现一个一个类只需要一个接口实现就可以了
方法的重载的时候,只根据函数签名去区分函数,而不是根据方法的返回值
10.内部类 1.内部成员类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package org.example;public class car { public class tnner { private String name; public static String school; public String getName () { return name; } public void setName (String name) { this .name = name; } } }
创建这个类的对象的时候需要这样
1 car.tnner test = new car ().new tnner ();
调用这里的school
1 System.out.println(car.tnner.school);
假设在内部类里面有一个方法test可以调用
直接
1 2 car.tnner test = new car ().new tnner (); test.test();
就可以直接调用这个函数
2.静态内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package org.example;public class car { public static class tnner { private String name; public static String school="123" ; public void test () { System.out.println("test" ); } public String getName () { return name; } public void setName (String name) { this .name = name; } } }
测试类
这里使用static修饰了这个方法
1 2 3 4 5 6 7 8 9 public class Main { public static void main (String[] args) { System.out.println(car.tnner.school); car.tnner test = new car .tnner(); test.test(); } }
3.局部内部类 将类和接口直接写入其他类,方法
4.匿名内部类 特殊的局部内部类
不需要为这个类声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package org.example;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { ctf web=new ctf (){ @Override public void zuolao () { System.out.println("web 坐牢" ); } }; web.zuolao(); } } abstract class ctf { public abstract void zuolao () ; }
这里创建了ctf这个抽象类,然后这里没有声明创建一个子类,但是这里的实际上的效果和子类一样
作用举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package org.example;import javax.swing.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.IOException;import java.util.ArrayList;import java.lang.*;import java.util.Random;import java.util.Scanner;public class Main { public static void main (String[] args) { JFrame win = new JFrame ("hello_world" ); JPanel panel= new JPanel (); win.add(panel); JButton btn = new JButton ("你好" ); panel.add(btn); panel.setSize(10 ,10 ); win.setSize(400 ,400 ); win.setLocationRelativeTo(null ); win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); win.setVisible(true ); btn.addActionListener(new ActionListener () { @Override public void actionPerformed (ActionEvent e) { } }); } }
这里的按钮事件监听器的时候,是使用了匿名内部类
11.枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package org.example;public enum test { a,b,c; private String name; private test () { } public String getName () { return name; } public void setName (String name) { this .name = name; } }
1 2 3 4 5 6 7 8 9 package org.example;public class Main { public static void main (String[] args) { test a1=test.a; System.out.println(a1); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 package org.example;public class Main { public static void main (String[] args) { test a1=test.a; System.out.println(a1.getName()); test a2=test.b; test[] as = test.values(); test a3 = test.valueOf("c" ); System.out.println(a3.name()); System.out.println(a3.ordinal()); } }
抽象枚举类
构建对象的时候需要重写对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package org.example;public enum test { a { @Override public void go () { } },b { @Override public void go () { } },c { @Override public void go () { } }; private String name="123" ; public abstract void go () ; public String getName () { return name; } public void setName (String name) { this .name = name; } }
这里创建了一个抽象的方法,需要重写相关的方法之后才能行
单例枚举类
这样的类的线程安全比较好
12.泛型 定义的时候使用了一个或者多个类型和类型,叫做泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package org.example;import java.util.ArrayList;public class Main { public static void main (String[] args) { ArrayList lixst=new ArrayList (); lixst.add("1" ); lixst.add("2" ); lixst.add(new String ("123" )); for (int i = 0 ; i < lixst.size(); i++) { System.out.println(lixst.get(i)); } } }
这里的ArrayList吗没有定义类型,就是一个泛型
如果使用<>去限制
在编译阶段能够帮助我们检查,同时约束了我们操作的类型
arraylist泛型原理 在arraylist源码里面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class ArrayList <E> extends AbstractList <E> implements List <E>, RandomAccess, Cloneable, java.io.Serializable E elementData (int index) { return (E) elementData[index]; } public E get (int index) { rangeCheck(index); return elementData(index); }
在这里送入的类,会被添加到e里面,然后通过e去获得,调用相关的函数。将相关的类型作为参数添加到函数里面去了
泛型类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package org.example;public class list <E>{ private Object[] arr = new Object [10 ]; private int size=0 ; public boolean add (E e) { arr[size]=e; size++; return true ; } public E get (int index) { return (E) arr[index]; } }
用object去储存这些不同的类型,在需要的时候可以使用强制类型转换去获得
也可以定义多个类型
1 2 public class list <E,T>
也可以用extend去限制某一个类的子类
1 public class list <E extend T>
泛型接口
13.map集合 map是一种双链数组
1 2 3 4 5 6 7 8 9 10 public class Main { public static void main (String[] args) { Map<String,Integer> map = new HashMap <>(); map.put("a" ,1 ); map.put("hello" ,23 ); System.out.println(map); } }
对于hashmap,无序,不重复,无索引
如果后面有键名重复的数据,会覆盖前面的数据
linkedhashmao是有序,不重复的,无索引的
treemap默认排序,不重复,无索引
map常见的操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package org.example;import javax.print.DocFlavor;import java.awt.image.ImageProducer;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import java.util.Set;public class Main { public static void main (String[] args) { Map<String,Integer> map = new HashMap <>(); map.put("a" ,1 ); map.put("hello" ,23 ); System.out.println(map); System.out.println(map.get("a" )); System.out.println(map.size()); map.remove("hello" ); System.out.println(map.containsKey("a" )); System.out.println(map.containsValue(2 )); map.clear(); System.out.println(map.isEmpty()); Set<String> key = map.keySet(); Set<Integer> key1 = (Set<Integer>) map.values(); } }
putall方法可以把map1里面的全部内容copy一份到map1里面
map的遍历方式 1.获取键名然后获取键值 1 2 3 4 5 6 7 8 9 Map<String,Integer> map = new HashMap <>(); map.put("a" ,1 ); map.put("hello" ,23 ); map.put("web" ,1 ); map.put("pwn" ,2 ); Set<String> keys = map.keySet(); for (String key:keys) { System.out.println(map.get(key)); }
使用set集合获取所有的键名,然后去遍历这个set集合,然后去获得这个key对应的值
2.将键值对作为一个整体去遍历
1 2 3 4 Set<Map.Entry<String, Integer>> list=map.entrySet(); for (Map.Entry<String, Integer> entry:list){ System.out.println(entry.getKey()+"==>" +entry.getValue()); }
把map对象里面的封装成对象,然后放到一个list里面,然后直接读取就好了
3.使用lambda
jdkb1.8之后才能用
1 map.forEach((k,v)-> System.out.println(k+"==>" +v));
这里就可以直接遍历了
14.反射 加载类,将方法直接加载到内存里面,然会允许使用变成来解析类里面的成分
获取这个class对象 1.类名字.class
2.直接Classforname 1 Class c2 = Class.forName("org.example.ctf" );
3.实例化对象然后调用getclass方法 1 2 ctf a = new ctf (); Class c3 = a.getClass();
获取构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package org.example;import javax.print.DocFlavor;import java.awt.image.ImageProducer;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import java.util.Set;import static sun.plugin.util.ProgressMonitor.get;public class Main { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class c1=ctf.class; Constructor[] constructors=c1.getConstructors(); for (Constructor constructor:constructors) { System.out.println(constructor.getName()+"==>" +constructor.getParameterCount()); } } } class ctf { String name = "web" ; int age = 114 ; public ctf () { System.out.println("test1" ); } public ctf (String name) { System.out.println("test2" ); } }
获取特定的构造器
1 2 Constructor c2 = c1.getConstructor(); System.out.println(c2);
1 Constructor c2 = c1.getConstructor(String.class);
这里就获取的有参数的构造器
反射创建对象
1 2 3 Constructor c2 = c1.getConstructor(); c2.newInstance();
这里调用无参数构造器
能够直接建立一个对象
1 ctf AsaL1n = (ctf) c2.newInstance();
也可以强制转换,禁止检查访问控制
1 2 c2.setAccessible(true ); ctf AsaL1n = (ctf) c2.newInstance();
获取类的成员对象和方法
同构造器,这里不说了
使用filed去获取成员
获取成员类
触发某一个方法 使用invoke方法
1 2 3 Class c1=ctf.class; Method m = c1.getMethod("hello" ); m.invoke(ctf.class.newInstance());
反射可以破坏封装的完整性
接下来开始学习java web了 每天学点序列化链子啥的,要期末考拉