一个demo学会java

全栈工程师开发手册 (作者:栾鹏)

快捷链接:
java开发大全

这篇demo较长,包含了java基本的内容,若不是出于校验自己java基础能力的朋友,建议按照上面的链接分章节学习。本demo包含了java的数组、对象、对象属性、接口,面向对象,重载,多态、封装、字符串、正则表达式、函数、参数、容器、算法、线程、异常等方面的知识,可以全面检验你的java学习效果。

此demo包括文件:测试文件index.java和接口interface1.java、接口interface2.java、基类Student.java、派生类Monitor.java文件

Student.java实现了一个java基类

//static int var=10;                                                            //java禁止使用全局数据
//一个包可以包含多个类,类默认访问修饰符为包访问,每个文件只能有一个public类,类只能是包访问或public
public class Student implements Comparable<Student>{                            //implements继承接口关键字,Comparable<Student>类比较接口
    public static void main(String[] args) {}                                   //每个类中都可以有一个main函数,用于调试

    public Student(){                                                           //不接受任何参数的叫默认构造器,没定义构造器,编译器会自动创建
        this("student",12);                                                     //通过this仅能调用一个构造器,必须将构造器调用置于起始处
        getname();                                                              //构造器会调用成员函数和数据,所有在初始化构造器前会初始化成员数据
        printf("基类无参构造器");                                              
    }
    public Student(String name,int age){                                        //有参构造器
        this.age = age;this.name = name;
        printf("基类有参构造器"+name);
    }
    public Student(String name,Character...args){                               //可变参数列表args是一个参数数组,重载方法中应只有一个可变参数列表,编译器
        this.name = name;
        printf("基类变参构造器");                                                 //args[0]表示变参中的第一个参数
    }
    public void setname(String name){this.name=name;printf("基类设置名称:"+name);} //this表示对当前对象的引用
    public String getname(){printf("基类获取名称"+name);return name;}             //使用public方法实现对private数据的控制,保证类内数据安全
    void setage(int age){printf("基类设置名称"+age);this.age=age;}
    private int getage(){return age;}                                           //private属于final方法

    static long time=10;                                                        //所有类型数据均可在定义时初始化,数据均有默认值,所有类的静态数据最先初始化
    private int age=0;                                                          //private外部不可以访问
    String name = "student";                                                    //不加访问修饰符,默认为包访问

    public enum allsex{man,woman}                                               //枚举类型,等价于类内组合class allsex{man,woman},枚举类型可以有构造函数,有几个枚举实例就调用几次构造函数
    class Sextype{                                                              //内部类,在内部类声明为static时为嵌套类,嵌套类不属于对象,而属于类名
        public void setsex(allsex sextype){                                     //枚举类型,可作为变量,相当于const
            printf("设置内部类性别");
            switch (sextype) {                                                  //枚举类型用在switch中,用于限制参数的可选项
            case man:sexstring="boy";break;  
            case woman:sexstring="girl";break;
            default:break;
            }
        }
        public Student getStudent(){
            sexstring+=name;                                                    //内部类,嵌套类可以任意访问外部类数据,无论嵌套多少层
            return Student.this;                                                //返回外部类引用,当内部类是static时,内部类不存在对外部类的引用
        }
        private String sexstring;
    }
    public static <T> void printf(T str)                                        //泛型方法,
    {
        System.out.println(str.toString());                                 //System.out.println打印输出
    }


    //重写equals虚函数,java中除了static和final都是虚函数,(private属于final方法)
    public final boolean equals(Student another){                               //final标记的函数不能被派生类重写
        printf("比较了两个基类");
        if(this.age==another.age && this.name==another.name)
            return true;
        return false;
    }
    //垃圾回收器准备收回对象占用内存时执行,java虚拟机并未面临内存耗尽的情形不会浪费时间执行垃圾回收,(垃圾回收:停止-复制,标记-清扫)
    public void finalize(){
        printf("基类对象"+name+"内存被收回");
    }
    void dispose(){
        printf("基类对象"+name+"清理函数");
    }

    @Override
    public int compareTo(Student arg0){                                         //要实现排序,必须要实现的比较接口
        return age<arg0.age?-1:(age==arg0.age?0:1);                             //返回-1表示小于,0不表示等于,1表示大于
    }

}





//一个文件可以包含多个类,但是文件名必须和public类名相同,否则只能使用默认的包访问权限
abstract class Teacher{                                                         //abstract关键字表示为抽象类
    abstract void setname();                                                    //abstract抽象方法
    public String getname(){return name;}                                       //使用public方法实现对private数据的控制,保证类内数据安全
    String name="teacher";                                                      //不加修饰符默认为报访问
}

Interface1.java定义了一个接口

public interface Interface1{                                                    //interface接口声明,完全抽象类
    abstract void init1();                                                      //abstract抽象方法,接口自动是public的,接口中,不能定义函数体,只能声明,abstract可以不写
    class manclass implements Interface1{                                       //接口内部类自动是public和static的。属于嵌套类,接口内部类实现接口函数,为了创建接口所有不同实现的公共代码
        @Override
        public void init1() {
            System.out.println("接口内部类,实现公共代码");
        }

    }
}

Interface2.java实现了一个派生接口

public interface Interface2<A> extends Interface1{                      //接口也支持继承,接口可以多继承,extends后可以有多个子接口,接口可以嵌套在类中<A>泛型接口
    abstract void init2(A name);                                        //abstract抽象方法,接口自动是public的
    void init1();                                                       //接口重写了函数

    int DEFAULT_GAE =12;                                                //接口中的任何域都是自动的static和final的,static final使用大写风格
    String DEFAULT_NAME ="name";  

}

Monitor.java文件实现了一个继承自Student,并继承自Interface1和Interface2的派生类

import java.util.EnumSet;


final class Monitor<T> extends Student implements Interface1,Interface2<String>{    //<>泛型,extends继承类,implements继承接口,final终态类,不能再被继承
    Monitor(){                                                                      //派生类无参构造器
        super("monitor");printf("派生类无参构造器");                                //关键字super显示调用基类构造器,printf调用基类函数
    }                                                                               //构造前会调用父类无参构造函数,如果父类没有构造函数,则会默认生成。如果有构造函数(无参),则会调用无参构造函数。如果只有有参构造函数,必须显示调用
    Monitor(int age){printf("派生类有参构造器");}                                   //派生类有参构造器,
    static Student mysStudent = new Student("monitor",12);                          //静态数据初始化只在调用时刻才会进行,在第一次创建类对象或者第一次访问静态数据时最先被初始化
    final static Student student1;                                                  //final用于,保持引用不变,对象可变
    static Student student2;
    static{                                                                         //静态块,仅执行一次,对象创建或静态数据访问时执行,仅定义对象的话不执行
        student1 = new Student();
        student2 = new Student();
        printf("派生类静态块执行");
    }
    //重写函数的返回类型可以是基类型的派生类型,访问权限必须大于原访问权限,子类抛出异常小于等于父类方法抛出异常
    public String getname(){                                                        //重写虚函数不需要关键字,因为在java中除了static和final都是虚函数(private属于final方法)
        printf("派生类获取名称:"+name);                                                //
        //name = super.name+"的派生";                                                  //super代表基类
        return name;
    }
    public int getage(){return 11;}                                                 //private不能重写,派生类重名,覆盖了基类私有方法


    String name="monitor";                                                              //同名变量和静态函数,不能动态绑定到基类引用上,和基类数据存储在不同的区域
    String task ="帮助老师管理班级";  

    private T a;                                                                    //设置泛型,也可以使用原始基类Object
    public T getT(){return a;}                                                      //设置泛型函数,泛型会自动擦除传递过来的对象的类信息
    public void setT(T a){this.a=a;printf("派生类设置泛型变量");}

    public enum Group{                                                              //枚举类型,函数枚举
        SHUXUE{void action(){printf("数学");}},
        YINGYU{void action(){printf("英语");}},
        YUNWEN{void action(){printf("语文");}};
        abstract void action();                                                     //每个枚举元素要实现的函数
    }

    EnumSet<Group> allgroup=EnumSet.of(Group.SHUXUE,Group.YINGYU);                  //EnumSet枚举集合,EnumMap枚举映射
    public void printfgroup(){
        for(Group g:allgroup)
            g.action();
    }


    @Override
    public void init2(String name) {                                                //泛型接口
        printf("派生类实现接口2初始化函数");
    }
    @Override
    public void init1() {
        printf("派生类实现接口1初始化函数,或接口2初始化函数");
    }

}

index.java文件实现了所有知识点的测试。

import java.io.ByteArrayInputStream;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.Stack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.prefs.Preferences;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.List;

import javax.naming.InitialContext;

public class index implements Runnable{                                         //Runnable多线程,任务接口,如果类不是抽象类,必须实现接口函数,可以创建Thread的派生类,Callable<>有返回值的线程接口

    static String stringtemp;                                                   //类内共享变量
    public static void main(String[] args)
    {

        printf("===========基类相关操作==============");
        Preferences prefs=Preferences.userNodeForPackage(index.class);          //Preferences只能存放基本类型和字符串的键值对
        prefs.put("default_name", "student");                                   //Preferences用作属性配置
        prefs.putInt("default_age", 12);
        Student.time+=Student.time<<2+0x21^26;                                  //静态数据,可以铜鼓类型访问,<<位左移动,低位补0,^按位异或,0X表示16进制
        Student student1=new Student();                                         //所有的对象都必须通过new来创建,基本数据类型可以定义创建
        student1.name = student1.name+1;                                        //访问类内数据,字符串+重载
        student1.setage(-2*-6);                                                 //通过类内函数访问类数据,一元减号用于转变数据的符号
        Student.Sextype student1_sextype = student1.new Sextype();              //创建内部类,必须通过外部类变量new构造
        student1_sextype.setsex(Student.allsex.man);                            //调用枚举类型
        Student student2=student1;                                              //仅是复制引用,两个变量名指向同一块内存
        if(student1==student2)                                                  //==和!=只是比较对象的引用,不比较对象内容
            if(student1.equals(student2))                                       //对象的比较实用equals,比较对象的实际内容,但是定义类的equals默认行为还是比较引用,要在自定义类中重写equals函数
                //if(1)                                                         //非布尔值不能用在逻辑表达式中
                printf("创建了两个相同的类引用");

        Field[] fileds = student1.getClass().getDeclaredFields();               //反射获取对象类的属性
        try{                                                                    //尝试运行代码
            for(Field field:fileds){
                if(!field.isAccessible())
                    field.setAccessible(true);                                  //设置对象属性可读取
                    Object obj=field.get(student2);                             //从实例对象中获取字段属性的值,(私有的没法获取,数值或对象统一为对象,没有值返回的)
            }
        }
         catch (Exception e) {
            printf("错误内容:"+e.toString());                                   //catch函数在try出错时调用,exception是所有异常类的基类,异常类可以捕获派生类异常
            e.printStackTrace(System.out);                                      //堆轨迹,出错原因和位置
            //throw e;                                                          //抛出异常,停止运行
        }
        finally{                                                                //finally函数总要执行
            printf("finally函数总要执行");
        }





        printf("===========派生类相关操作==============");
        Monitor monitor1 =new Monitor(Interface2.DEFAULT_GAE);                      //基类构造函数(绑定后函数),派生类成员,派生类构造函数,接口中的域相当于枚举常量
        monitor1.name = "monitor1";                                                 //基类静态-派生类静态-基类私有-基类构造-派生类私有-派生类构造。函数在构造前已经存在
        printf("===========11111111111111111==============");
        sprintf(monitor1,null);                                                     //可变参数,null为参数为空
        sprintf(monitor1);                                                          //传递实现接口的类,向上转型为接口,实现函数回调
        printf("===========2222222222222222==============");
        Student student3 = new Monitor();                                       //基类引用,派生类对象
        student3.getname();                                                     //调用引用动态绑定的方法
        ((Monitor)student3).getage();                                           //向下转型成功,getage为派生类的公共函数


        printf("===========接口相关操作==============");
        Interface1 interface1=new Monitor();                                    //向上转型,interface1是基类,普通类,接口,无所谓,实现接口的类(包括内部类),都可以向上转型转化为接口
        interface1.init1();                                                     //调用动态绑定的函数
        interface1=getInterface1();                                             //通过匿名内部类实现接口函数的实现
        interface1.init1();


        printf("===========容器相关操作==============");
        //Collection接口,独立元素序列(List接口,Set接口,Queue接口)
        //List接口,插入顺序保存数组,(ArrayList数组,LinkedList链表)
        //Set接口,不能重复元素,(HashSet散列函数,TreeSet红黑树,LinkedHashList链表下的散列)
        //Queue接口,先进先出队列,(LinkedList链表,PriorityQueue优先级队列)

        //Map接口,键值对(字典,映射),HashMap(快速访问),TreeMap(键值排序),LinkedHashMap(保持元素插入顺序,通过散列提供快速访问)
        //list整体赋值,Arrays.asList方法返回的ArrayList是继承自AbstractList,不可变大小数组,作为参数生成可变大小的ArrayList
        List<String> allname = new ArrayList<String>(Arrays.asList("小明","小红","晓刚","小刘"));  //ArrayList实现向上转型为list接口,动态连续数组,<>内的对象类型可以不写,不能是基本,<>内类型擦除,编译器无法获取,
        allname.set(2,"小刚");                                                    //list元素赋值
        if(!allname.contains("小王"))                                             //元素包含
            allname.add("小王");                                                  //添加元素
        allname.remove(0);                                                      //删除元素
        stringtemp=allname.get(1);                                              //读取元素
        Iterator<String> iterator = allname.iterator();                         //集合的迭代器,next为首个元素的迭代器,ListIterator迭代器更厉害
        iterator.next();                                                        //指向第一个元素
        iterator.remove();                                                      //删除迭代器的对应元素,删除可以继续使用此元素的迭代器了
        while(iterator.hasNext())                                               //迭代器是否有一下个元素
            printf(iterator.next());                                            //获取序列的下一个元素

        Stack<String> allname1 = new Stack<String>();                           //stack先进后出堆栈,各种队列和栈基于LinkedList链表实现
        LinkedList<String> allname2 = new LinkedList<String>();                 //双端队列,队列
        Set<String> allname3 = new HashSet<String>();                           //不重复集合
        Map<String,String> map = new HashMap<String,String>();                  //或者是SortedMap
        map.put("小明", "12");
        Object x_name = map.get("小明");
        Iterator iterator1 = map.entrySet().iterator();                         //Map对象有keySet方法,返回key的Set集合,values()返回Collection集合,entrySet函数返回集合,元素类型为Map.Entry(一个<key,vlaue>的泛型接口)
        Map.Entry entry = (Map.Entry)iterator1.next();
        Object key=entry.getKey();
        Iterator iterator2 = map.keySet().iterator();
        key=iterator2.next();
        x_name=map.get(key);
        for(Map.Entry<String, String> entry2:map.entrySet()){
            entry2.getKey();
            entry2.getValue();
        }
        List<Map.Entry<String, String>> info_student= new ArrayList<Map.Entry<String,String>>(map.entrySet());







        printf("===========字符串相关操作==============");                                                             
        StringBuilder sb = new StringBuilder();                             //StringBuilder包括insert,replace,substring,reverse,append,tostring,delete方法
        sb.append(String.format("这里%s字符串相关操作", "shi"));             //string.format()格式化函数,内部创建formatter类设置字符串格式
        String outStr=sb.toString().replace("shi", "是");                    //string是不可变量,取值变化是生成新的类,replace替换,repalceAll,replaceFirst
        outStr=outStr.substring(3)+outStr.length();                         //substring取子字符串,length字符串长度,+重载连接字符串和整型
        if(outStr.indexOf("shi")<0)                                         //indexof插叙子字符串所在位置,不存在返回-1,其他字符串相关操作较多
            printf("字符串\""+outStr+"\"不存在指定子字符串");
        outStr = "luanpeng luanpeng";
        outStr=outStr.split(" ")[0];                                        //split分割字符串,返回数组,读取第一个数组赋值给outstr
        Pattern pattern = Pattern.compile("lu[a-n]");                       //创建正则法则,将正则字符串编译成正则表达式
        Matcher matcher = pattern.matcher(outStr);                          //创建匹配器
        while (matcher.find())                                              //依次查询是否存在匹配项
            printf(matcher.group()+"起点"+matcher.start()+"终点"+matcher.end());//group匹配值,start起始位置,end结束位置
        matcher.reset("luan");                                              //将正则法则重新使用到新的字符串上

        Integer nn= Integer.parseInt("123");                                //字符串转化为整型
        String str = String.valueOf(nn);                                    //整型转化为字符串
        char[] temparr ={'a','b'};                                          //字符数组
        str=new String(temparr);                                            //字符数组转化为字符串
        temparr = str.toCharArray();                                        //字符串转化为字符数组
        byte[] temp1=str.getBytes();                                        //字符串转化为字节数组

        StringBuffer buf=new StringBuffer();                                //字符串的StringBuffer表示,
        buf.append(str+"\r\n");                                             //StringBuffer可以追加
        buf.deleteCharAt(buf.length()-1);                                   //StringBuffer与StringBuilder有很多类似功能,这里不一一列举




        printf("===========数组相关操作==============");
        Random random =new Random(17);                                          //随机数
        int farrat[] =new int[10];                                              //数组创建int var[] 和int[] var等效
        for(int x:farrat){                                                      //for语句的遍历形式
            x=random.nextInt();                                                 //读取伪随机序列
        }
        Student[] all1 = new Student[7];  
        Student[] all2 = new Student[10]; 
        Arrays.fill(all1, student1);                                            //数组填充,填充对象时,只是填充了引用
        Arrays.fill(all2, student3);
        System.arraycopy(all1, 0, all2, 2, all1.length);                        //ii第0个开始复制到jj第2个开始,长度ii.length
        Arrays.sort(all2);                                                      //调用重写的比较函数执行数组排序
        int location = Arrays.binarySearch(all2, student1);                     //在数组中查找,不存在返回-1
        if(!Arrays.equals(all1, all2))                                          //数组相等   个数和每个元素均相等
            printf(Arrays.toString(all2));  

        Monitor<Student> monitor2 = new Monitor<Student>();                         //包含泛型的类型调用,也可以不使用泛型创建对象
        monitor2.setT(student1);


        //注解
        //数据流
        //序列化
        printf("===========线程相关操作==============");
        new index().run();                                                      //在主线程中调用线程类中的run函数,不是多线程,只是调用函数
        Thread thread=new Thread(new index());                                  //调用子函数,执行线程类中run函数,thread构造参数为runnable接口,线程类向上转型为接口
        thread.setDaemon(true);                                                 //设置线程为后台线程,否则为非后台线程
        thread.start();                                                         //线程启动,thread.join()等待线程执行完毕
        thread.interrupt();                                                     //线程中断,会在线程运行至阻塞时中断,弹出中断异常
        ExecutorService exec= Executors.newCachedThreadPool();                  //创建线程池管理器
        exec.execute(new index());                                              //向线程管理器中添加一个线程实现接口,自动执行
        exec.submit(new index());                                               //调用有返回的线程
        exec.shutdown();                                                        //关闭线程管理器,线程池继续运行

        synchronized (stringtemp) {                                             //对象锁控制同步块,需要锁才能进入
            try {
                printf("进入同步块,释放对象锁");                                  //对象释放锁,进入等待锁定池,当接收到对象notify、notifyAll后进入对象锁定池,准备重新获取对象继续执行
                stringtemp.wait();                                              //wait,会抛出异常,synchronized 的目标与 wait() 方法的物件不相同,会有 IllegalMonitorStateException
                printf("同步控制块恢复继续执行");                                  //java里面有专门捕获异常的try catch。异常是向上依次抛出的,如果在某一层被捕获就不会退出。如果一直没有被捕获直到抛出到系统层就是退出。
            } catch (InterruptedException e) {                                  //中断异常类,会在线程运行至阻塞时中断,弹出中断异常
                e.printStackTrace();
            }
        }



        printf("结束");
        printf(Student.allsex.woman);


    }


    public static void sprintf(Student student,Object[] args)                   //基类参数允许传递派生类引用,//Object[] args用于可变参数列表,可以无参调用
    {
        student.setname("student1");                                            //调用引用动态绑定的方法-基类函数,修改的是基类属性
        student.getname();                                                      //调用引用动态绑定的方法-派生类重写的虚函数,获取的是派生类属性
    }
    public static void sprintf(Interface1 interface1)                           //接口参数允许传递接口类为参数,sprintf函数名相同实现重载
    {
        if(interface1 instanceof Monitor){                                      //判断引用的类型是否是指定类型
            Student student=(Student)interface1;                                //先向下转型为monitor,在向上转型为student
            printf("接口类型:"+interface1.getClass().getName());                //获取引用指向的对象类型
            student.getname();                                                  //调用动态绑定的方法
        }
        interface1.init1();                                                     //接口相当于纯抽象类,调用动态绑定的方法   
    }



    public static Interface1 getInterface1() {                                  //不用创建实现接口的类,而直接实现接口的方法的定义
        return new Interface1(){                                                //匿名内部类,可以传递参数
            public void init1(){
                System.out.println("通过匿名内部类实现向上转型为接口");
            }
        };
    }


    public static synchronized <T> void printf(T str)                           //泛型方法,synchronized同步函数,检查锁,获取锁,执行代码,释放锁
    {
        System.out.println(str.toString());
    }

    int num=0;
    @Override                                                                   //多线程,任务接口,只有调用线程接口才会执行
    public void run(){                                                          //线程接口重载函数
        Thread.currentThread().setPriority(++num);                              //设置线程优先级,优先级不会导致死锁,优先级低的执行频率低
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");      //设置日期格式
        printf(df.format(new Date())+"执行了线程"+num);                          // new Date()为获取当前系统时间
        Lock lock = new ReentrantLock();                                        //创建线程锁
        lock.lock();                                                            //锁定资源
        try {
            Thread.yield();                                                     //线程让步,不释放锁,yield不能设置时间,只能控制同优先级
            Thread.sleep(1000);                                                 //sleep可以使低优先级的线程得到执行的机会,线程睡眠,不释放锁,保持监控,自动恢复,sleep不操作锁,所以可以在非同步控制方法(块)中调用
        } catch (Exception e) {
            printf(df.format(new Date())+"线程错误"+e.toString());
        }
        finally{
            lock.unlock();                                                      //释放锁
            printf(df.format(new Date())+"释放锁");                    
            synchronized (stringtemp) {                                         //对象锁控制同步块,需要锁才能进入
                stringtemp.notifyAll();                                         //stringtemp调用线程恢复通知所有等待线程,wait、notify、notifyAll必须在同步控制方法(块)中调用                                             
            }
        }

    }

}

猜你喜欢

转载自blog.csdn.net/luanpeng825485697/article/details/78148248