Java基础

1. JAVA异常分类及处理

概念
如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1. 异常处理方式

  1. 抛出,抛给调用者
    在这里插入图片描述
    throw是语句抛出一个异常,一般是在代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常
    在这里插入图片描述

  2. try catch 捕获异常针对性处理

2. Java反射

在这里插入图片描述

package com.tedu.fanshe;

public class Person {
	private String name;
	private int age;
	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 getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public void Test(){
		System.out.println("无参测试方法");
	}
	public void Test(String name,int age){
		System.out.println(name+"带参测试方法");
	}
	
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
}

package com.tedu.fanshe;

public class Student extends Person{
	
	private boolean score;

	public boolean getScore() {
		return score;
	}

	public void setScore(boolean score) {
		this.score = score;
	}

	
}


package com.tedu.fanshe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
	public static void main(String[] args) throws Exception {
		package com.tedu.fanshe;

public class Test3 {
	public static void main(String[] args) throws Exception {
		/**
		 * 得到类对象
		 */
		Class c1 = Class.forName("com.tedu.fanshe.Person");
		Class c2 = Person.class;
		Class c3 = "com.tedu.fanshe.Person".getClass();
		Class c4 = new Person().getClass();
	
		/**
		 * 反射获取对象
		 */
		Object o1 = c1.newInstance();//默认使用无参
		Constructor con1 = c1.getConstructor(String.class,int.class);
		Object o2 = con1.newInstance("小明",18); //带参构造方法
	
		
		/**
		 * 操作反射得到的对象
		 */
		Person p = (Person)o1;
		p.getAge();
		p.getName();
		
		
		
		
		/**
		 * 反射获取属性对象
		 */
		//Field f1 = c1.getField("name");//获取公有属性
		Field f2 = c1.getDeclaredField("name");//获取声明过的属性
	
		f2.setAccessible(true);//允许访问私有成员
	
		/**
		 * 反射操作属性
		 */
		f2.set(o1, "敬仰"); //为name属性赋值
		Object object = f2.get(o1);//获取name的值
		System.out.println(o1);
		System.out.println(o2);
		
		/**
		 * 反射获取方法对象
		 */
		Method m1 = c1.getMethod("Test", String.class,int.class);
		Method m2 = c1.getMethod("Test");
		
		/**
		 * 反射操作方法
		 * invoke: 唤醒
		 */
		Object invoke1 = m1.invoke(o1, "小张",19); 
		m2.invoke(o1);
	
		
	}
}

3. Java注解

概念 : JDK1.5后新特性,用来说明程序的
在这里插入图片描述

在这里插入图片描述
生产文档
cmd——> javadoc xxx.class

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.1. 元注解: 用于描述注解的注解

@Target
描述注解能够作用的位置
在这里插入图片描述

@Retention
描述注解被保留的阶段
在这里插入图片描述
在这里插入图片描述

@ Documented
描述注解是否被抽取到api文档中

@Inherited
描述注解是否被子类继承,子类继承父类后也会被注解修饰

3.2. 反射获取注解信息

package zhujie;

public class Demo1 {
	public void show(){
		System.out.println("demo2----show---");
	}
}
package zhujie;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.lang.model.element.Element;

/**
 * 描述需要执行的类名,方法名
 *
 */

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface properties {
	String className();
	String methodName();
	
	
}

package zhujie;

import java.lang.reflect.Method;



@properties(className="zhujie.Demo1",methodName="show")
public class ReflectTest {
	public static void main(String[] args) throws Exception{
		//1.解析注解
		
		//1.1获取该类的字节码文件对象
		Class<ReflectTest> c = ReflectTest.class;
		//2. 获取上边的注解对象
		//其实就是在内存中生成了一个该注解接口的子类实现对象
		properties an = c.getAnnotation(properties.class);
		
		//3.调用注解对象中定义的抽象方法,获取返回值
		String className = an.className();//zhujie.Demo1
		String methodName = an.methodName();//show
		
		/*public class propertieslmpl implements properties{
			String className(){
				return "zhujie.Demo1";
			}
			String methodName(){
				return "show";
			}
		  }
		*/

		Class<?> c2 = Class.forName(className);
		Method m = c2.getMethod(methodName);
		m.invoke(c2.newInstance());
	}
	
}

4. Java内部类

在这里插入图片描述
内部类的作用: 防止类名冲突,实现多继承



4.1. 静态内部类

package base;


/**外部类*/
public class Out extends Demo1{
	private static String name="waibu";
	private int age;
	
	static int a= 10;
	void print(){System.out.println("Out--->print");}
	
	
	public static class Inner extends Demo2{
		int a= 20;
		/**静态内部类可以访问外部类所有的静态 变量及方法,即使私有*/
		void print(){System.out.println(name);}
	    
		public void Test(){
	    	System.out.println(Out.a);
			
	    	System.out.println(a);
	    	print();
	    }
	}
	
	
	public static void main(String[] args) {
		/**
		 * 静态内部类也叫做嵌套类,可以单独拿出使用
		 */
		Inner inner = new Inner();
		inner.Test();
	}
}



4.2. 成员内部类

定义在类内部的非静态类,就是成员内部类。成员内部类不能修饰静态方法和静态变量

package base;


/**外部类*/
public class Out extends Demo1{
	private static String name;
	private int age;
	
	int a= 10;
	void print(){System.out.println("Out--->print");}
	
	/**
	 * 内部类可以调用外部类的所有属性、方法
	 */
	public class Inner extends Demo2{
		int a= 20;
		void print(){System.out.println("Inner--->print");}
	    
		public void Test(){
			/**获取外部类的资源*/
	    	System.out.println(Out.this.a);
	    	Out.this.print();
	    	
	    	System.out.println(a);
	    	print();
	    }
	}
	
	
	public static void main(String[] args) {
		Inner inner = new Out().new Inner();
		inner.Test();
	}
	
}




4.3. 局部内部类

定义在方法中的类,就是局部内部类

package base;


/**
 *  局部内部类: 方法里面的内部类
 *  1. 只能在方法里面时候,出了方法体就不可见
 *  2. 局部内部类只能向上转型为父类或者接口类型才能对外可见
 *
 */
public class Test {
	
	public Her fun(){
		class Out implements Her{
			@Override
			public void test() {System.out.println("Out--->Test()");}
			
		}
		return new Out();
	}
	
	
	public static void main(String[] args) {
		Test t2 = new Test();
		Her her = t2.fun();//用方法创建接口对象
		her.test();
	}
}

package base;

public interface Her {
	int i=1;
	public void test();
}

4.4. 匿名内部类

要继承一个父类或者实现一个接口

package base;

public class Test {
	/**
	 * 匿名内部类 : 即使类也是对象
	 * 装饰者模式
	 */
	public Her fun(){
		return new Her(){
			public void test(){
				System.out.println("her-->test()");
			}
		};
	}
	
	/** lambda*/
	Her h = () -> {System.out.println("lambda");};
	
	public static void main(String[] args) {
		new Test().fun().test();
		new Test().h.test();
	}
}




5. Java泛型

在这里插入图片描述

在这里插入图片描述

package fanxing;

public class generic<T> {
	
	private T key;
	public  generic(T key){
		this.key = key;
	}
	
	public T getKey(){
		return key;
	}
}

package fanxing;


public class Test {
	public static void main(String[] args) {
		/**
		 * 泛型类在创建对象的时候,来指定操作的具体数据类型
		 */
		generic<String> g = new generic<>("hello");
		String key = g.getKey();
		System.out.println(key);
		
		/**
		 * 如果不指定泛型,那么类型就是Object类型
		 */
		generic g2 = new generic("你好");
		
		/**
		 * 泛型类不支持基本数据类型
		 */
		//generic<int> g3 = new generic<>(3);
		
		
		
		/**
		 * 同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型
		 * 
		 */
		generic<Integer> g4 = new generic<>(10);
		
		System.out.println(g.getClass()==g4.getClass());//true
		
	}
}



在这里插入图片描述

5.1. 泛型类

package fanxing3;

public class Parent<E> {
	private E value;
	
	public E getValue(){
		return value;
	}
	public void setValue(E value){
		this.value = value;
	}
}

package fanxing3;


/**
 * 泛型类派生子类,子类也是泛型类,那么子类的泛型标示要和父类一致
 */
public class ChildFirst extends Parent<Object> {	
	@Override
	public Object getValue() {
		return super.getValue();
	}
	
}

package fanxing3;


/**
 * 父类明确类型
 */
public class ChildFirst2<T> extends Parent<T> {	
	@Override
	public T getValue() {
		return super.getValue();
	}
	
}

在这里插入图片描述

在这里插入图片描述

5.2. 泛型方法

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述



5.3. 类型通配符

在这里插入图片描述

package fanxing5;

public class Box<E> {
	private E first;

	public E getFirst() {
		return first;
	}

	public void setFirst(E first) {
		this.first = first;
	}
	
	
}

package fanxing5;

public class Test {
	public static void main(String[] args) {
		Box<Number> box1 = new Box<>();
		box1.setFirst(100);
		showBox(box1);
	}
	/*
	public static void showBox(Box<Number> box){
		Number first = box.getFirst();
		System.out.println(first);
	}
	public static void showBox(Box<Integer> box){
		Number first = box.getFirst();
		System.out.println(first);
	}
	*/
	/**
	 * 泛型通配符
	 */
	public static void showBox(Box<?> box){
		Object first = box.getFirst();
		System.out.println(first);
	}
	
	
}

在这里插入图片描述

在这里插入图片描述



5.4. 类型消除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述



5.5. 泛型数组在这里插入图片描述

声明泛型数组引用

package fanxing6;

import java.util.ArrayList;
import java.util.Arrays;

public class fanxingArray2 {
	public static void main(String[] args) {
		ArrayList<String>[] strList = new ArrayList[5]; //数组中的元素是动态数组
		
		ArrayList<String> strList2 = new ArrayList<>(); 
		strList2.add("abc");
		System.out.println(strList2); //[abc]
		
		strList[0]=strList2;
		String s = Arrays.toString(strList);
		System.out.println(s);//[[abc], null, null, null, null]
	}
	
}



通过反射创建泛型数组

package fanxing6;

import java.lang.reflect.Array;

public class Fruit<T> {
	private T[] array;
	@SuppressWarnings("unchecked")
	public Fruit(Class<T> clz,int length){
		//通过Array.newInstance创建泛型数组
		array = (T[]) Array.newInstance(clz, length);
	}
	
	public void put(int index, T item){
		array[index] = item;
	}
	
	public T get (int index){
		return array[index];
	}
	
	public T[] getAll(){
		return array;
	}
}

package fanxing6;

import java.util.Arrays;

@SuppressWarnings("all")
public class Test {
	public static void main(String[] args) {
		Fruit fruit = new Fruit(String.class,10);
		fruit.put(0, "猫");
		fruit.put(1, "苟");
		fruit.put(2, "蛇");
		
		String string = Arrays.toString(fruit.getAll());
		System.out.println(string);
	}
}

6. Java序列化

在这里插入图片描述
序列化就是把对象改成二进制的过程,可以保存到磁盘或者进行网络传输

  1. java.io.Serializable
  2. java.io.Externalizable
  3. ObjectInputStream
  4. ObjectOutputStream

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

6.1 如果某个变量不希望实现序列化?

变量声明成静态变量 static
变量声明成静态变量 transient

6.2 序列化的作用

  1. 方便传输,速度快,还很安全,调用方反序列化即可拿到传输前最原始的java对象,常用于不同进程之间的对象传输
  2. 方便存储,不管是存储成文件还是数据库,都行,存储为文件,下回要用可以直接反序列拿到对象

6.3 UID值的作用

  用于判断序列化文件是否已经失效(过期)。序列化的时候会把这个ID写到文件里。读的时候会把这个ID和代码里的ID比较,如果不一致,表示文件里的已经失效

不写会有什么问题?
  不写的话,序列话的时候,JVM会帮你动态的生成一个。这个动态生成的算法可能在不同的虚拟机里不一样,也就是不同的环境下生成的可能不同。这就会有一个问题,你序列化产生的文件,别人读的时候会 InvalidClassException

7. Java拷贝

在Java语言中,当我们需要拷贝一个java对象的时候,常见的会有两种方式的拷贝: 浅拷贝与深拷贝。

需要拷贝的对象需要实现Cloneable接口,重写clone()方法

7.1 浅拷贝

说明:
为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?
在运行时刻,Object中的clone()识别出你要复制的是哪一个对象.,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象
继承自Java.lang.Object类测clone()方法时浅复制
在这里插入图片描述
浅拷贝: 只复制对象中的基本类型,,而引用类型不复制,它指向的还是原来的对象

package Cpoy;

public class Test01 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Stu s= new Stu();
		s.setAge(20);
		s.setName("邓圣");
		
		Stu s2 =(Stu)s.clone();
		
		System.out.println(s2.getAge());//说明被复制对象的所有变量(基本数据类型)都含有与原来的对象相同的值
		System.out.println(s2.getName());
		
		System.out.println("==========================");
		
		System.out.println(s.getName().equals(s2.getName())); //true,说明没有创建新的对象
		
		//s2.setName("黄振");   //指向了一个新的对象
		//System.out.println(s2);
		
		/**
		 * 对任何的对象x,都有x.clone() != x   
		 */
		System.out.println(s==s2);//false,克隆对象与原对象不是同一个对象
	
		/**
		 * 对任何的对象x,都有x.clone().getClass() == x.getClass();  true
		 */
		System.out.println(s2.getClass()==s.getClass());//克隆对象与原对象类型相同
	
	
		System.out.println(s.clone().equals(s2)); //克隆对象与原对象不指向同一内存地址
	}
	
}


class Stu implements Cloneable{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	@Override
	public String toString() {
		return "Stu [age=" + age + ", name=" + name + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	
	 
}


7.2 深拷贝

在这里插入图片描述
深拷贝: 复制对象中的基本类型和引用类型

package Cpoy;

public class Test02 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Teacher t = new Teacher();
		t.setAge(20);
		t.setName("邓圣");
		Stu2 s = new Stu2();
		s.setId(01);
		s.setUrl("127.0.0.1");
		s.setTeacher(t);
		
		Stu2 s2 = (Stu2) s.clone();
		
		System.out.print("修改之前的值: ");
		System.out.println(s);
		/**
		 * 同过s2对象来修改Stu2中的引用变量Teacher
		 */
		s2.getTeacher().setName("黄老板");
		System.out.print("修改之后的值: ");
		System.out.println(s);
		
		System.out.println(s2);//指向了新的对象,说明拷贝了Teacher类型
		
		/**
		 * 说明: 被引用类型不会复制,只会复制八大基本类型
		 */
		
		/**
		 * 思考如何通过clone实现深复制
		 * 我们在复制Stu2时,同时也复制Teacher
		 */
	}
}
class Teacher implements Cloneable{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Teacher [age=" + age + ", name=" + name + "]";
	}
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	
}

class Stu2 implements Cloneable{
	private int id;
	private String url;
	private Teacher teacher;
	
	/*浅拷贝
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	*/
	
	/**
	 * 深拷贝,拷贝了引用类型
	 */
	@Override
	public Stu2 clone() throws CloneNotSupportedException {
		/*Stu2 stu2 = (Stu2)super.clone();
		stu2.setTeacher((Teacher)stu2.getTeacher().clone());
		
		 返回的Stu2对象中,封装了一个新的Teacher()
		 
		return stu2;*/
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try ( ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);){
            oos.writeObject(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        try ( ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);){
            Stu2 objcet = (Stu2)ois.readObject();
            return objcet;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
	}
	
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Teacher getTeacher() {
		return teacher;
	}

	public void setTeacher(Teacher teacher) {
		this.teacher = teacher;
	}

	@Override
	public String toString() {
		return "Stu2 [id=" + id + ", url=" + url + ", teacher=" + teacher + "]";
	}	
	
}



8. JavaIO

绝对路径是一个完整的路径,例如:C:\\Users\\a.txt
相对路径是一个简化的路径,相对指的是相对于当前项目的根目录,如果使用当前项目的根目录,路径可以简化书写


File类常用方法

public String getAbsolutePath(),返回此File的绝对路径名字符串
public String getPath(),将此File转换为路径名字符串
public string getName(),返回由此File表示的文件或目录的名称
public long length(),返回由此File表示的文件的长度
public boolean exists(),此File表示的文件或目录是否实际存在
public boolean isDirectory(),此File表示的是否为目录
public boolean isFile(),此File表示的是否为文件
public boolean createNewFile(),当且仅当具有该名称的文件尚不存在时,创建一个新的空文件
public boolean delete(),删除由此File表示的文件或目录
public boolean mkdir(),创建由此File表示的目录
public boolean mkdirs(),创建由此File表示的目录,包括任何必需不存在的父目录
public String list(),返回一个String数组,表示该File目录中所有子文件或目录
public File[] listFiles(),返回一个File数组,表示该File目录中所有的子文件或目录


什么是IO
  数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入input输出output,即流向内存是输入流,流出内存的输出流。

输入流把数据从其他设备上读取到内存中的流
输出流把数据从内存中写出到其他设备上的流
输入流输出流
字节流字节输入流
InputStream
字节输出流
outputStream
字符流字符输入流
Reader
字符输出流
Writer


java.ioFileOutputStream 文件字节输出流
把内存中的数据写入到文件中

FileOutputStream(String name)创建一个具有指定名称的文件中写入数据的输出文件流
FileOutputStream(File file)创建一个向指定File对象表示的文件中写入数据的文件输出流
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值