Java 基础

java基础

复习一下java,以下是java复习阶段的一些知识点

1、+=扩展

 public class self_plus_test {

	public static void main(String[] args) {

		short s = 1;
		s+=1;
		System.out.println(s);
	}

}

分析:s += 1逻辑上可以看成是s = s + 1,计算结果被提升为int,再向short赋值时发生错误,但是 s = s + 1进行了两次运算,+=是一个运算符,只运算一次,并带有强制转换的特点,也就是说s += 1就是s = (short)(s + 1),因此编译没有问腿,结果为2.

2、byte

public class constant_variable_test {

	public static void main(String[] args) {

		byte b1 = 1;
		byte b2 = 2;
		byte b3 = 1 + 2;
		byte b4 = b1 + b2;
		System.out.println(b3);
	}

byte b3 = 1 + 2; 1 + 2可以确定值在byte的范围内,赋值给b3没有问题,但b1 b2是变量,编译器无法确定具体的值,会将结果以int类型进行处理,但int不能赋值给byte,便易出错。

3、方法的参数问题

方法的参数是基本数据类型时,传递的是值,当方法的参数是引用数据类型时,传递的是地址

4、成员变量的默认值

数据类型默认值
基本类型整数(byte, short, int, long)0
浮点(float, double)0.0
字符(char)‘\u0000’
布尔(boolean)false
引用类型数组、类、接口null

5、线程安全

synchronized解决线程同步问题

5.1 同步代码块
package cn.learnj.ficca.advanced;

public class TicketRunnableImp implements Runnable{
    private int ticket = 100;
    Object lock = new Object();
    @Override
    public void run() {
        //窗口永远开启
        while (true){
            synchronized (lock){
                if(ticket > 0){//有票
                    try {
                        //模拟出票操作,使用sleep模拟出票时间
                        Thread.sleep(100);//此时仍占有锁,只不过没有cpu执行权
                        System.out.println("");

                    }catch (Exception e){
                        e.printStackTrace();

                    }

                    String name = Thread.currentThread().getName();
                    System.out.println(name + "正在卖" + ticket--);
                }//出了同步代码块,归还锁🔐
            }

        }
    }
}

package cn.learnj.ficca.advanced;

public class TicketTest {
    public static void main(String[] args) {
        //创建线程任务对象
        TicketRunnableImp ticket = new TicketRunnableImp();
        Thread t1 = new Thread(ticket,"窗口1");
        Thread t2 = new Thread(ticket, "窗口2");
        Thread t3 = new Thread(ticket, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

5.2 同步方法

非static方法,锁对象是this

static方法,锁对象是当前方法所在类的字节码对象(类名.class)

package cn.learnj.ficca.advanced.ticket.method;

public class RunnableImp implements Runnable {
    private int ticket = 100;
    @Override
    public void run() {
        while (true){
            sellTicket();
        }
    }

    //同步方法,锁对象是this, 即创建的run对象
    private synchronized void sellTicket() {
        if(ticket > 0){//有票
            try {
                //模拟出票操作,使用sleep模拟出票时间
                Thread.sleep(100);
                System.out.println("");

            }catch (Exception e){
                e.printStackTrace();

            }

            String name = Thread.currentThread().getName();
            System.out.println(name + "正在卖" + ticket--);
        }
    }
}

package cn.learnj.ficca.advanced.ticket.method;

public class RunnableTest {
    public static void main(String[] args) {
        RunnableImp run = new RunnableImp();

        Thread t1 = new Thread(run, "窗口1");
        Thread t2 = new Thread(run, "窗口2");
        Thread t3 = new Thread(run, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

5.3 锁机制
 java.util.concurrent.locks.lock

机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块和同步方法具有的功能Lock都有,更体现面向对象思想。

Lock锁也称同步锁,加锁和释放锁方法化。

加同步锁:

public void lock()

释放同步锁:

pubic void unlock()

使用如下:

package cn.learnj.ficca.advanced.lock.ticket;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class lockRunnable implements Runnable{
    private int ticket = 100;
    Lock lock = new ReentrantLock();
    @Override
    public void run() {
        //窗口永远开启
        while (true){
           lock.lock();
                if(ticket > 0){//邮票
                    try {
                        //模拟出票操作,使用sleep模拟出票时间
                        Thread.sleep(100);
                        System.out.println("");

                    }catch (Exception e){
                        e.printStackTrace();

                    }

                    String name = Thread.currentThread().getName();
                    System.out.println(name + "正在卖" + ticket--);
                }

            lock.unlock();
        }
    }
}

package cn.learnj.ficca.advanced.lock.ticket;

import cn.learnj.ficca.advanced.demo01.ticket.TicketRunnableImp;

public class lockTest {
    public static void main(String[] args) {
        //创建线程任务对象
        lockRunnable run = new lockRunnable();

        Thread t1 = new Thread(run,"窗口1");
        Thread t2 = new Thread(run, "窗口2");
        Thread t3 = new Thread(run, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

6、线程池

Java里面线程池的顶级接口是 java.util.concurrent.Executor ,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口java.util.concurrent.ExecutorService

java.util.concurrent.Executors 线程工厂类里面提供了一些静态工厂,生成一些常用的线程池。官 方建议使用Executors工程类来创建线程池对象。

Executors类中有个创建线程池的方法如下:

  • public static ExecutorService newFixedThreadPool(int nThreads) : 返回线程池对象

  • public Future<?> submit(Runnable task) : 获取线程池中的某个线程对象,并执行

    Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用。

    使用线程池中线程对象:

    • 1、创建线程池对象
    • 2、创建Runnable接口子类对象
    • 3、提交Runnable接口子类对象
    • 4、关闭线程池(一般情况下不做)
    package cn.learnj.ficca.advanced.threadpool;
    
    import com.sun.jdi.ThreadReference;
    
    public class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println("我要一个教练!" + Thread.currentThread().getName());
            try{
                Thread.sleep(2000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("教练来了:" + Thread.currentThread().getName());
            System.out.println("教我游泳,教完后,教练回到了游泳池");
        }
    }
    
    
    package cn.learnj.ficca.advanced.threadpool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ThreadPoolDemo {
        public static void main(String[] args) {
            //创建线程池对象
            ExecutorService service = Executors.newFixedThreadPool(2);
            //创建Runnable实例对象
            MyRunnable r = new MyRunnable();
    /*
            //手动创建线程的方式
            Thread t = new Thread(r);
            t.start();
    */
            //从线程池中获取线程对象,然后调用MyRunnable中的run()
            service.submit(r);
            //再获取一个线程对象,调用MyRunnable中的run()
            service.submit(r);
            service.submit(r);
            //tips: submit方法调用结束之后程序并不终止,因为线程池控制着线程的关闭
            //将使用完的线程归还到线程池中
            //结束线程
    //        service.shutdown();
    
        }
    }
    
    

7、Lambda表达式

即函数式编程,重点在于做什么,而不是怎么做

7.1 Lambda表达式的标准格式为:
(参数类型 参数名称) ‐> { 代码语句 }
7.2 省略规则
  • 参数类型可省略
  • 仅有1个参数,小括号可省略
  • 大括号内仅有一条语句,无论是否有返回值,都可以省略大括号,return关键字及语句分号
7.3 使用前提
  • 必须具有接口,且接口中仅有一个抽象方法

    tips: 有且仅有一个抽象方法的接口,称为”函数式接口“.

  • 必须具有上下文推断,即方法的参数或局部变量类型必须为lambda对应的接口类型,才能使用lambda作为该接口的实例

以下是实现多线程的一个例子:

package cn.learnj.ficca.advanced.lambda;

public class ThreadLambdaTest {
    public static void main(String[] args) {
        new Thread(() -> {
            System.out.println("多线程任务执行(使用lambda表达式)");
            System.out.println(Thread.currentThread().getName());
        }, "lambda").start();
    }
}

8、序列化 反序列化

示例:

package cn.learnj.ficca.advanced.seriable;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private String pwd;

    public Student() {
    }

    public Student(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public String getPwd() {
        return pwd;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

package cn.learnj.ficca.advanced.seriable;

import java.io.*;
import java.util.ArrayList;

public class SerTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建学生对象
        Student student = new Student("赵", "z");
        Student student1 = new Student("鞠", "j");
        Student student2 = new Student("杨", "y");

        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(student);
        arrayList.add(student1);
        arrayList.add(student2);
        //序列化操作
        serializ(arrayList);

        //反序列化操作
        //rserializ();
        
    }

    private static void serializ(ArrayList<Student> arrayList) throws IOException {
        //创建序列化流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));;
        //写出对象
        oos.writeObject(arrayList);
        //释放资源
        oos.close();

    }

    //反序列化
    private static void rserializ() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.txt"));
        //读取对象,强转为ArrayList类型
        ArrayList<Student> list = (ArrayList<Student>) ois.readObject();
        for (int i = 0; i < list.size(); i++) {
            Student s = list.get(i);
            System.out.println(s);
        }
            

    }
}

9、反射

9.1 获取Class对象的方式:
  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
    • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  2. 类名.class:通过类名的属性class获取
    • 多用于参数的传递
  3. 对象.getClass():getClass()方法在Object类中定义着。
    • 多用于对象的获取字节码的方式
  • tips:
    同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
9.2 Class对象的功能
9.2.1 获取成员变量
  • Field[] getFields() :获取所有public修饰的成员变量
  • Field getField(String name) 获取指定名称的 public修饰的成员变量
  • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
  • Field getDeclaredField(String name)
  • Field:成员变量
    • 相关操作:
      1. 设置值

        • void set(Object obj, Object value)
      2. 获取值

        • get(Object obj)
      3. 忽略访问权限修饰符的安全检查

        • setAccessible(true):暴力反射
package cn.learnj.ficca.advanced.reflection;

public class Person {
    private String name;
    private int age;

    public int a;
    protected int b;
    int c;
    private int d;
    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public int getB() {
        return b;
    }

    public void setB(int b) {
        this.b = b;
    }

    public int getC() {
        return c;
    }

    public void setC(int c) {
        this.c = c;
    }

    public int getD() {
        return d;
    }

    public void setD(int d) {
        this.d = d;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a=" + a +
                ", b=" + b +
                ", c=" + c +
                ", d=" + d +
                '}';
    }

    public void work(){
        System.out.println("我愿汗水流尽: ");
    }

    public void work(String why){
        System.out.println("我愿汗水流尽: " + why);
    }
}

package cn.learnj.ficca.advanced.reflection;

import java.lang.reflect.Field;

public class ReflectDemo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //0.获取Person类的Class对象
        Class<Person> personClass = Person.class;
    /*
        1. 获取成员变量们
        * Field[] getFields() :获取所有public修饰的成员变量
        * Field getField(String name)   获取指定名称的 public修饰的成员变量

        * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
        * Field getDeclaredField(String name)
    */
        //1. Field[] getFields() :获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-------------");

        //2.Field getField(String name)
        Field a = personClass.getField("a");
        //获取成员变量a的值
        Person person = new Person();
        Object value = a.get(person);
        System.out.println(value);
        //设置a的值
        a.set(person,10);
        System.out.println(person);

        System.out.println("---------");

        //Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //在本例中,d是private类型,本不能在类外访问,在此可以使用暴力反射去访问d
        //忽略访问权限修饰符的安全检查
        Field d = personClass.getDeclaredField("d");
        d.setAccessible(true);//暴力反射
        Object value2 = d.get(person);
        System.out.println(value2);

    }
}

9.2.2 获取构造方法
  • Constructor<?>[] getConstructors()
  • Constructor getConstructor(类<?>… parameterTypes) : 参数类型(比如String.class)
  • Constructor getDeclaredConstructor(类<?>… parameterTypes)
  • Constructor<?>[] getDeclaredConstructors()

获取构造方法是为了创建对象

  • Constructor:构造方法
    • 创建对象:
      • T newInstance(Object… initargs)

      • 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法, 如

        Person p = personClass.newInstance()
        

        获得一个Person对象

package cn.learnj.ficca.advanced.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo2 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        //0.获取Person类的Class对象
        Class<Person> personClass = Person.class;
    /*
        1. 获取构造方法们(为了创建对象)
			* Constructor<?>[] getConstructors()
			* Constructor<T> getConstructor(类<?>... parameterTypes)

			* Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
			* Constructor<?>[] getDeclaredConstructors()
    */

        //Constructor<T> getConstructor(类<?>... parameterTypes)
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象
        Person person = constructor.newInstance("赵", 23);
        System.out.println(person);

        System.out.println("-----------");
        //使用空参构造
        Constructor<Person> constructor1 = personClass.getConstructor();
        System.out.println(constructor1);
        //创建对象
        Person person1 = constructor1.newInstance();
        System.out.println(person1);

        System.out.println("--------------");
        //空参构造一般使用这种方式
        Person person2 = personClass.newInstance();
        System.out.println(person2);

    }
}
9.2.3 获取成员方法
  • Method[] getMethods()
  • Method getMethod(String name, 类<?>… parameterTypes)
  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, 类<?>… parameterTypes)

获取成员方法是为了执行方法

  • Method:方法对象
    • 执行方法:

      • Object invoke(Object obj, Object… args)
    • 获取方法名称:

      • String getName:获取方法名
package cn.learnj.ficca.advanced.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectDemo3 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //0.获取Person类的Class对象
        Class<Person> personClass = Person.class;
    /*
        1. 获取成员变量(是为了执行方法)
        * Method[] getMethods()
        * Method getMethod(String name, 类<?>... parameterTypes)
        * Method[] getDeclaredMethods()
        * Method getDeclaredMethod(String name, 类<?>... parameterTypes)
    */
        //1. Method getMethod(String name, 类<?>... parameterTypes) 获取指定名称的方法
        //空参
        Method work_method = personClass.getMethod("work");
        Person p = new Person();
        //执行方法
        work_method.invoke(p);

        System.out.println("-----------");

        //有参
        Method work_method2 = personClass.getMethod("work", String.class);
        //执行方法
        work_method2.invoke(p, "不留遗憾");

        System.out.println("---------");

        //2. Method[] getMethods() 获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            System.out.println(method.getName());//获取方法名 
//            method.setAccessible(true);
        }
    }
}

9.2.4 获取类名
				//获取类名
        String name = personClass.getName();
        System.out.println(name);
9.3 反射案例

需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
实现:
1. 配置文件
2. 反射
步骤:
1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2. 在程序中加载读取配置文件
3. 使用反射技术来加载类文件进内存
4. 创建对象
5. 执行方法

package cn.learnj.ficca.advanced.reflectpro;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @program: basic-code
 * @description: This is a program of reflection.
 * @author: Mr.Luo
 * @create: 2020-01-29 18:05
 */
//同样使用Person类
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //1.加载配置文件
        //1.1 创建Properties对象
        Properties properties = new Properties();
        //1.2 加载配置文件,转换为一个集合
        //1.2.1 获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
        properties.load(resourceAsStream);

        //2. 获取配置文件中定义的数据
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");

        //3. 加载该类进内存
        Class cls = Class.forName(className);

        //4. 创建对象
        Object obj = cls.newInstance();

        //5. 获取方法对象
        Method method = cls.getMethod(methodName);

        //6. 执行方法
        method.invoke(obj);
        
    }
}

9.4 操作获取Class对象
  • 获取Class对象的方式:
    1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
      • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2. 类名.class:通过类名的属性class获取
      • 多用于参数的传递
    3. 对象.getClass():getClass()方法在Object类中定义着。
      • 多用于对象的获取字节码的方式
package cn.learnj.ficca.advanced.reflectpro;

/**
 * @program: basic-code
 * @description: Threes ways of getting the object of Class
 * @author: Mr.Luo
 * @create: 2020-01-29 21:13
 */
public class ReflectDemo1 {
    /*
       * 获取Class对象的方式:
       1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
       2. 类名.class:通过类名的属性class获取
       3. 对象.getClass():getClass()方法在Object类中定义着。
   */
    public static void main(String[] args) throws ClassNotFoundException {
       //1. Class.forName("全类名")
        Class cls1 = Class.forName("cn.learnj.ficca.advanced.reflectpro.Person");
        System.out.println(cls1);

        //2. 类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);

        //3. 对象.getClass
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3); //三者均为 class cn.learnj.ficca.advanced.reflectpro.Person

        //比较三个对象是否相同
        System.out.println(cls1 == cls2);//true
        System.out.println(cls1 == cls3);//true
        //即同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
    }
}

10、注解
  • 概念:说明程序的。给计算机看的

  • 注释:用文字描述程序的。给程序员看的

  • 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

  • 概念描述:

    • JDK1.5之后的新特性
    • 说明程序的
    • 使用注解:@注解名称
  • 作用分类:
    ①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
    ②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
    ③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
  • JDK中预定义的一些注解
    • @Override :检测被该注解标注的方法是否是继承自父类(接口)的
    • @Deprecated:该注解标注的内容,表示已过时
    • @SuppressWarnings:压制警告
      • 一般传递参数all @SuppressWarnings(“all”)
  • 自定义注解
    • 格式:
      元注解
      public @interface 注解名称{
      属性列表; //本质是成员方法
      }

    • 本质:注解本质上就是一个接口,该接口默认继承Annotation接口

      • public interface MyAnno extends java.lang.annotation.Annotation {}
  • 属性:接口中的抽象方法
    * 要求:
    1. 属性的返回值类型有下列取值
    * 基本数据类型
    * String
    * 枚举
    * 注解
    * 以上类型的数组

    	2. 定义了属性,在使用时需要给属性赋值
    		1. 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
    		2. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
    		3. 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
    
  • 元注解:用于描述注解的注解
    * @Target:描述注解能够作用的位置
    * ElementType取值:

    	- TYPE:可以作用于类上
    	
    	* METHOD:可以作用于方法上
    	* FIELD:可以作用于成员变量上
    	
    * @Retention:描述注解被保留的阶段
    	
    	* @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
    	
    * @Documented:描述注解是否被抽取到api文档中
    
    * @Inherited:描述注解是否被子类继承
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值