Java基础知识小结(内部类、BigInteger、枚举、接口、重写重载和序列化)

一、Java内部类

1、内部类

在Java中,也可以嵌套类(类中的类)。嵌套类的目的是将属于同一类的类分组,这使代码更具可读性和可维护性。
要访问内部类,请创建外部类的对象,然后创建内部类的对象:

class OuterClass {
  int x = 10;

  class InnerClass {
    int y = 5;
  }
}

public class MyMainClass {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.y + myOuter.x);
  }
}

// 输出 15 (5 + 10)

2、私有的内部类

与"常规"类不同,内部类可以是private 私有的或 protected受保护的。 如果不希望外部对象访问内部类,请将该类声明为private:

class OuterClass {
  int x = 10;

  private class InnerClass {
    int y = 5;
  }
}

public class MyMainClass {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.y + myOuter.x);
  }
}

3、Static 内部类

内部类也可以是static静态的,这意味着您可以在不创建外部类的对象的情况下访问它:
与 static静态属性和方法一样,static静态内部类无权访问外部类的成员

class OuterClass {
  int x = 10;

  static class InnerClass {
    int y = 5;
  }
}

public class MyMainClass {
  public static void main(String[] args) {
    OuterClass.InnerClass myInner = new OuterClass.InnerClass();
    System.out.println(myInner.y);
  }
}

// 输出 5

4、从内部类访问外部类

内部类的一个优点是,它们可以访问外部类的属性和方法:

class OuterClass {
  int x = 10;

  class InnerClass {
    public int myInnerMethod() {
      return x;
    }
  }
}

public class MyMainClass {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.myInnerMethod());
  }
}

// 输出 10

二、Java大数BigInteger、BigDecimal

如果基本的整数和浮点数精度不够用,可以使用java.math包中的BigInteger、BigDecimal类处理包含任意长度的数字序列的数值。

1、BigInteger实现任意精度的整数运算

大数的创建

//valueOf()方法将普通的数值转换为大数
        BigInteger a=BigInteger.valueOf(100);
        //使用一个带字符串参数的构造器
        BigInteger b=new BigInteger("1332433344333");
        //内置常量ZERO、ONE这些
        BigInteger c=BigInteger.ZERO;

大数的运算

Scanner in=new Scanner(System.in);
        String s1=in.nextLine();
        String s2=in.nextLine();
        BigInteger a=new BigInteger(s1);
        BigInteger b=new BigInteger(s2);
        //加法add()
        BigInteger c=a.add(b);
        System.out.println(c);
        //乘法multiply()
        BigInteger d=a.multiply(b);
        System.out.println(d);
        //减法subtract()
        BigInteger e=a.subtract(b);
        System.out.println(e);
        //除法divide()
        BigInteger f=a.divide(b);
        System.out.println(f);
        //取余数mod()
        BigInteger g=a.mod(b);
        System.out.println(g);

其他方法

Scanner in=new Scanner(System.in);
        String s1=in.nextLine();
        String s2=in.nextLine();
        BigInteger a=new BigInteger(s1);
        BigInteger b=new BigInteger(s2);
        //开平方根
        //BigInteger c=a.sqrt();//java 9才有
        //比较两个大数的大小
        // ab返回正数,a==b返回0
        int num=a.compareTo(b);
        String flag= num>=0 ? (num>0 ? "a大":"相等"):"b大";
        System.out.println(flag);

2、BIgDecimal 实现任意精度的浮点数运算

其他方法与BIgInteger类似

Scanner in=new Scanner(System.in);
        String s1=in.nextLine();
        String s2=in.nextLine();
        BigDecimal a=new BigDecimal(s1);
        BigDecimal b=new BigDecimal(s2);
        //除法,并指定舍入方式
        BigDecimal c=a.divide(b,BigDecimal.ROUND_HALF_UP);//四舍五入

三、Java中常量、枚举类型

1、常量

特点:

  • 在程序运行过程中一直不会改变,用关键字final修饰,也被称为“final变量”;
  • 在整个程序中只能被赋值一次,赋值后便不可修改,为所有对象共享;
  • 常量名一般使用全大写;

声明常量的标准语法:

final 数据类型 常量名=;

如果要使某个常量在一个类的多个方法中都能够使用,可以声明为类常量,使用 static final 修饰

public class Main
{
    public static final double PI=3.14;
    public static void main(String[] args)
    {
        System.out.println(PI*2*2);
    }
}

当定义的final变量属于类常量时,必须在定义的时候就赋值,否则会出错。

public class Main
{
    static final double PI=3.14;//必须在定义时就赋值
    public static void main(String[] args)
    {
        final double p;//可以分开
        p=2.2;
        System.out.println(PI*p*2);
    }
}

2、枚举类型

变量的取值只在一个有限的集合内,枚举类型包括有限个命名的值。
例如,杯子有小中大三种型号

public class Main
{
    public enum Size{SMALL,MEDIUM,LARGE};
    public static void main(String[] args)
    {
        Size cupSize=Size.SMALL;
        System.out.println(cupSize);
    }
}
SMALL

比较两个枚举类型的值时,可以直接使用==。
枚举类的定义

public enum Size
    {
        SMALL("S"),MEDIUM("M"),LARGE("L");
        private String cupSize;
        //构造器总是私有的,所以private可以忽略不写
        Size(String cupSize)
        {
            this.cupSize=cupSize;
        }
        public String getCupSize()
        {
            return cupSize;
        }
    }

枚举类型中的常用方法
Java基础知识小结(内部类、BigInteger、枚举、接口、重写重载和序列化)_第1张图片
综合应用:

import java.util.*;
public class Main
{
    public enum Size
    {
        SMALL("S"),MEDIUM("M"),LARGE("L");
        private String cupSize;
        //构造器总是私有的,所以private可以忽略不写
        Size(String cupSize)
        {
            this.cupSize=cupSize;
        }
        public String getCupSize()
        {
            return cupSize;
        }
    }
    public static void main(String[] args)
    {
        Scanner in=new Scanner(System.in);
        String input=in.next().toUpperCase();
        Size size=Enum.valueOf(Size.class,input);//将普通字符串转换为枚举实例
        System.out.println("size="+size);
        System.out.println("cupSize="+size.getCupSize());
        if(size==Size.MEDIUM)
        {
            System.out.println("YES");
        }
    }
}

medium
size=MEDIUM
cupSize=M
YES

四、Java使用接口

1、定义接口

接口中的方法是抽象的、公有的,一个类可以实现多个接口。

Java 8 新增:引入默认方法,静态方法,用default关键字来定义
Java 9 新增:私有方法和私有静态方法,用private修饰,私有方法必须包含方法体,必须是具体方法,且私有方法只能在该接口内使用或访问。

2、引用接口

关键字:implements
定义接口

package 基础语法;

public interface JieOne {
	int add(int a,int b);
}

引用接口

package 基础语法;

class SiZeYunSuan implements JieOne,JieTwo,JieThree,JieFour{
	public int add(int a,int b) {
		return a+b;
	}
	public int sub(int a,int b) {
		return a-b;
	}
	@Override
	public int umul(int a, int b) {
		// TODO 自动生成的方法存根
		return a/b;
	}
	@Override
	public int mul(int a, int b) {
		// TODO 自动生成的方法存根
		return a*b;
	}
	
}
public class UseInterface {
	public static void main(String[] args) {
		SiZeYunSuan t=new SiZeYunSuan();
		System.out.println("a+b="+t.add(2, 5));
		System.out.println("a-b="+t.sub(2, 5));
		System.out.println("a*b="+t.mul(2, 5));
		System.out.println("a/b="+t.umul(2, 5));
	}
}

在接口的实现过程中规定:

能为所有的接口提供实现的功能; 能遵循重写的所有规则; 能保持相同的返回数据类型。 接口完全支持多继承,可以有多个直接父接口,用英文逗号隔开。

五、Java方法的重写和重载

1、重写

建立在继承关系上,在子类中重新编写来自父类的方法来满足需求。

规则:

重写方法不能比被重写方法限制更严格的访问级别,即访问权限可以扩大不能缩小; final修饰的方法和静态方法都不能重写;
返回类型和参数列表保持相同; 抽象方法必须在具体类中重写;
无论被重写方法是否抛出异常,重写方法都可以抛出任何非强制异常;但重写方法不能抛出新的强制性异常,或则比被重写方法声明的范围更广的强制性异常。反之则可以。

2、重载overload

同一类中可以有两个或多个方法具有相同的方法名,但是要保证它们的参数不同,

方法重载中参数列表不同的含义是:参数的个数不同或者是参数类型不同。另外,返回类型不能用来区分方法重载

package 基础语法;

public class Chongzai {
	int max(int a,int b) {
		System.out.println("int max:");
		return a>b?a:b;
	}
	int max(short a,short b) {
		System.out.println("int max(short):");
		return a>b?a:b;
	}
	public static void main(String args[]) {
		Chongzai tChongzai=new Chongzai();
		tChongzai.max(3, 4);
		short a=3;//先定义为short,否则默认int
		short b=4;
		tChongzai.max(a, b);
		
	}
}

六、序列化

1、序列化与反序列化

package com.java.main;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class TestObject
{
	public static void main(String[] args)
	{
		ObjectStream objectStream = new ObjectStream();
		objectStream.testObjectOutputStream();
		objectStream.testObjectInputStream();
	}
}
class ObjectStream
{
	/*
	 * 序列化过程:将内存中的Java对象保存到磁盘中或者通过网络传输出去
	 */
	public void testObjectOutputStream()
	{
		ObjectOutputStream oos = null;
		try
		{
			oos = new ObjectOutputStream(new FileOutputStream("D:\\CODE\\codeeclipse\\Java基础\\src\\com\\java\\main\\data.txt"));
			oos.writeObject(new String("你好Java"));
			oos.flush(); // 刷新一下
		}catch(IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(oos != null)
			{
				try
				{
					oos.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
	/*
	 * 反序列化过程:将磁盘中的对象还原成内存中的Java对象
	 * 
	 */
	public void testObjectInputStream()
	{
		ObjectInputStream ois = null;
		try
		{
			ois = new ObjectInputStream(new FileInputStream("D:\\CODE\\codeeclipse\\Java基础\\src\\com\\java\\main\\data.txt"));
			Object obj = ois.readObject();
			String string = (String)obj;
			System.out.println(string);
		}catch(IOException e)
		{
			e.printStackTrace();
		} catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}finally
		{
			if(ois != null)
			{
				try
				{
					ois.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
}

自定义的类的对象如果需要序列化与反序列化,就需要实现Serializable接口,而且该类要提供一个全局常量serialVersionUID(用来标识序列化版本)
自定义类的所有属性都必须可序列化

class Person implements Serializable
{
	/**
	 * 需要提供一个全局常量 serialVersionUID 
	 */
	private static final long serialVersionUID = 1L;
	
	private String name;
	private int age;
	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;
	}
	@Override
	public String toString()
	{
		return "Person [name=" + name + ", age=" + age + "]";
	}	
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestObject
{
	public static void main(String[] args)
	{
		ObjectStream objectStream = new ObjectStream();
		objectStream.testObjectOutputStream();
		objectStream.testObjectInputStream();
	}
}
class ObjectStream
{
	/*
	 * 序列化过程:将内存中的Java对象保存到磁盘中或者通过网络传输出去
	 */
	public void testObjectOutputStream()
	{
		ObjectOutputStream oos = null;
		try
		{
			oos = new ObjectOutputStream(new FileOutputStream("D:\\CODE\\codeeclipse\\Java基础\\src\\com\\java\\main\\data.txt"));
			oos.writeObject(new Person("张三", 21)); // 序列化自定义的类对象person
			oos.flush(); // 刷新一下
		}catch(IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(oos != null)
			{
				try
				{
					oos.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
	/*
	 * 反序列化过程:将磁盘中的对象还原成内存中的Java对象
	 * 
	 */
	public void testObjectInputStream()
	{
		ObjectInputStream ois = null;
		try
		{
			ois = new ObjectInputStream(new FileInputStream("D:\\CODE\\codeeclipse\\Java基础\\src\\com\\java\\main\\data.txt"));
			Object obj = ois.readObject();
			Person person = (Person)obj;
			System.out.println(person);
		}catch(IOException e)
		{
			e.printStackTrace();
		} catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}finally
		{
			if(ois != null)
			{
				try
				{
					ois.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
}

2、RandomAccessFile

既可以实现输入,也可以实现输出

package com.java.main;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class TestRandom
{
	public static void main(String[] args)
	{
		RandomAccessFile raf1 = null;
		RandomAccessFile raf2 = null;
		try
		{
			raf1 = new RandomAccessFile(new File("C:\\Users\\zzps\\Pictures\\Saved Pictures\\手写签名照.jpg"), "r");
			raf2 = new RandomAccessFile(new File("C:\\Users\\zzps\\Pictures\\Saved Pictures\\手写签名照1.jpg"), "rw");
			
			byte[] bBuffer = new byte[1024];
			int len;
			while((len = raf1.read(bBuffer)) != -1)
			{
				raf2.write(bBuffer, 0, len);
			}
		}catch(IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(raf1 != null)
			{
				try
				{
					raf1.close();
				} catch (IOException e)
				{
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
			}
			
			if(raf2 != null)
			{
				try
				{
					raf2.close();
				} catch (IOException e)
				{
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
			}
		}
	}
}

你可能感兴趣的:(Java基础知识汇总,Java基础知识,Java基础教程,java,开发语言)