java基础知识汇总

a.面向过程

a1. 数值类型空间占用:

	byte   1B  2的8次方   -128到127
	short  2B  2的16次方  -32768到32767
	int    4B  2的32次方  -2147483648到2147483647
	long   8B  2的64次方  -2的63次方 到 2的63次方-1
	float  4B  -->1.3f
	double 8B  -->1.3d
	char   2B  '\u' 代表十六进制Unicode码值 97 <=> a <=> '\u0061'

a2. 两个byte类型的变量运算结果为int类型,因为CPU中寄存器的存储空间为4字节,需要强制类型转换

a3. 在java中0和1不能代表真和假

a4. 字符串运算(A)

	'a' + 'b' + 'c' 表示相加
	"a" + "b" + "c" 表示相连

a5. 字符串运算(B)

	"1" + 2 + 3 结果为 123
	 1 + 2 + "3" 结果为 33

a6. 局部变量

  • b1. 必须先赋值后使用
  • b2. 作用范围是定义它到定义它的代码块结束
  • b3. 重合范围内不允许两个局部变量命名冲突

a7. 表达式一定有值

a8. 数组:一次定义多个变量,并且在内存中分配多个连续的存储空间

  • b1. 数组在分配空间后,初始化默认值为0

      int[] a = new int[5];
      int[] a = {100, 90 , 80, 70 , 85};
      int[] a = new int[]{100, 90 , 80, 70 , 85};
    
  • b2. 二维数组

    • c1. int[][] a = new int[3][4]; --> a.length = 3; //表示a的行数

        图例---> {89, 90, 70, 60}
        		  {89, 90, 70, 60}
        		  {89, 90, 70, 60}
      
    • c2. 还可以分开定义二维数组

        int[][] a = new int[3][];
        
        a[0] = new int[3];
        a[1] = new int[4];
        a[2] = new int[2];
      
    • c3. 一次性定义二维数组并赋值

        int[][] a = {{1,2,4}, {3,4,5,6}, {5,9,8,7,3}};
      
  • b3. java.util.Arrays.sort(a); //为数组a从小到大排序

b. 面向对象

b1. 编程思想:如何把一个问题细化成每一个可行的步骤

  • c1. 符合思维习惯
  • c2. 各司其职,各尽所能
  • c3. 弱耦合性
  • c4. 可重用性
  • c5. 可扩展性

b2. 面向对象的设计原则

  • c1. 单一职责原则 --> 一个类,最好只做一件事,只有一个原因引起它的变化
  • c2. 开放封闭原则 --> 对扩展开放,对修改封闭
  • c3. 依赖倒置原则 --> 依赖于抽象,就是对接口编程,不要对实现编程
  • c4. 接口隔离原则 --> 使用多个小的专门的接口,而不要使用一个大的总接口
  • c5. Liskov替换原则 --> 子类必须能够替换其基类

b3. 类 – > 对象的抽象,是客观事物(对象)在人脑中的主观反映

b4. 实例变量 --> 在类的内部定义的非静态属性

  • c1. 不要求先赋值后使用
  • c2. 访问范围至少为本对象的内部
  • c3. 当实例变量与局部变量发生命名冲突的时候局部变量优先

b5. 方法的声明

  • c1. 修饰符

  • c2. 参数表

  • c3. 返回值

  • c4. 方法名

  • c5. 抛出的异常

      注: 在java中如果有多个修饰符,顺序可以互换,如下:
      static public void main(String[] args){}
    

b6. 方法重载 --> 方法名相同,参数表不同 (编译的时候识别重载)

b7. 构造方法

  • c1. 无返回类型
  • c2. 系统默认提供一个无参的构造方法,前提是我们没有手写任何构造方法
  • c3. 在对象构造时自动调用一次
  • c4. 方法名必须和类名相同

b8. 对象内存结构

  • c1. 堆内存 --> 只包含成员变量
  • c2. 栈内存 --> 局部变量(对象类型存对象引用,即堆内存地址)
  • c3. 常量池 --> 静态变量或常量
  • c4. 方法区 --> 对象的方法(即使new出多个对象也只存在一个方法)

b9. java中创建对象的方法

  • c1. new
  • c2. clone()
  • c3. 对象序列化
  • c4. 反射

b10. 深克隆和浅克隆

  • c1. 浅拷贝 --> 拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象

      实现方法:
      d1. 实现Cloneable接口
      d2. 重写clone()方法
      	  public Object clone(){
      		return super.clone();
      	  }
    
  • c2. 深拷贝 --> 不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象

      实现方法:
      d1. 实现Cloneable接口
      d2. 重写clone()方法
      	  public Object clone(){
      		//将引用的对象也拷贝一份并重新赋值
      	  }
      注:用序列化与反序列化的方式也可以实现深拷贝
    

b11. 关键字this表示当前对象,this()用来在有参的构造方法中调用无参的构造方法,而且为构造方法的第一个语句

b12. java方法参数传递规则 --> 简单类型传值,对象类型传引用

b13. String变量存储空间

  • c1. String是不可变类,不可以被继承并且值不会发生改变

      --> 源码定义 private final char value[];
    
  • c2. JVM维护了一个字符串常量池,每当创建字符串变量时,JVM首先检查字符串常量池,如果常量池中已经存在,则返回池中的字符串对象引用,否则创建该字符串对象并放入池中

      String a = "abc";//这种方式会放入常量池中
    
  • c3. 当使用new String(String str)方式等创建字符串对象时,不管字符串常量池中是否有与此相同内容的字符串,都会在堆内存中创建新的字符串对象

  • c4. intern()方法返回字符串对象在字符串常量池中的对象引用,若字符串常量池中尚未有此字符串,则创建一新的字符串常量放置于池中。

      System.out.println(a == a.intern());
    
  • c5. 字符串比较:

    • d1. if(a == b) //比较的是字符串的引用地址
    • d2. int value = s.compareTo(s1);//依次比较每个字符的字符编码
    • d3. boolean b = s.equals(s1);//判断两个字符串对象的内容是否相同

b14. 继承 --> 父类是子类共性的抽象

  • c1. 子类只能继承一个父类,单继承是为了满足树状关系的简单性
  • c2. 覆盖
    • d1. 父类和子类的方法名、返回值、参数表都相同叫做覆盖
    • d2. 子类方法的修饰符一定要等于或者宽于父类方法的权限
    • d3. 子类继承了父类中的方法定义,用自己的特殊实现替换掉父类提供给他的一般实现
    • d4. 覆盖只存在于方法之间,属性定义相同叫遮盖
  • c3. 父类和子类之间也可以出现重载
  • c4. 构造一个子类对象时一定会先构造它的父类对象,父类对象会成为子类对象的一部分
  • c5. 父类的私有属性和方法都可以继承到子类,只是子类无法访问,因此也可以说父类的私有属性和方法不可以继承到子类

b15. 访问权限规则:

访问修饰符访问范围继承关系
private只有本类内部可以访问不能继承
default本类加本包可以访问同包可以继承
protected本类+本包+不同包的子类可以
public公开可以

b16. 对象的构造过程

  • c1. 无继承关系
    • d1. 分配空间(把所有属性赋值null或0)
    • d2. 初始化属性(不包括类变量)
    • d3. 调用一个构造方法
  • c2. 有继承关系
    • d1. 分配空间(子类和父类都分配空间)
    • d2. 递归的构造父类对象
    • d3. 初始化本类属性
    • d4. 调用本类的构造方法

b17. super -->指向父类对象,往往用于在子类中访问父类被遮盖的属性或者被覆盖的方法

  • c1. super(s)调用父类带参数的构造方法
  • c2. super(s)写在子类构造方法的第一行

b18. 多态 --> 编译时类型(父类)与运行时类型(子类)不同

  • c1. 子类对象可以当作父类对象,这是多态的本质

  • c2.

      Animal a = new Dog();
      Dog d = (Dog)a;//必须强制类型转换,否则编译出错
    
  • c3. 多态的特点:

    • d1. 对象运行时类型永远不变
    • d2. 只能调用其编译时类型中定义的方法(强转后则可调用子类的特殊方法)
    • d3. 运行时会根据运行时类型去找覆盖后的方法
  • c4. dog instanceof Animal ;//如果对象是这个类或者其子类则返回true

  • c5. 多态的作用 --> 把子类当父类对象来看,可以屏蔽不同子类的差异

  • c6.

      public A method(B b){};
    
    • d1. method方法允许以B对象或B的子类对象为参数
    • d2. 也允许以A对象或者A对象的子类为返回值

b19. static --> 全类公有(本类中所有对象公用一个空间)

  • c1. 能修饰属性、方法、初始化代码块、内部类

  • c2. 修饰变量

      public int a;//实例变量
      public static int b;//类变量,访问b也可以 A.b 即 类名.类变量
    
  • c3. 修饰方法

      public static void print(){};//静态方法,访问print也可以 A.print() 即 类名.类方法
    
  • c4. 静态属性的存在与否与对象无关

  • c5. 静态代码块

      static{ };//静态代码块 --> 当类被加载时{}中的内容会被执行一次,只一次,因为类的加载只有一次
    
  • c6. 注意

    • d1. 在静态方法中不允许访问类的非静态成员,也不允许出现this
    • d2. 静态方法只能覆盖静态方法,但是不会出现多态性

b20. 类加载

此过程要先于对象构造,当JVM第一次使用一个类的时候,会通过ClassPath找到对象的.Class文件,把文件内容读入JVM并保存起来。类加载的最终产品是位于堆区中的Class对象,该Class对象封装了类在方法区内的数据结构

  • c1. 类加载的过程

    • d1. 装载:查找和导入Class文件;
    • d2. 链接:把类的二进制数据合并到JRE中;
      • e1. 校验:检查载入Class文件数据的正确性;
      • e2. 准备:给类的静态变量分配存储空间(赋默认值);
      • e3. 解析:将符号引用转成直接引用;
    • d3. 初始化:对类的静态变量(赋值),静态代码块执行初始化操作
  • c2. 类加载器 --> 双亲委派模型(自下而上检查,自上而下加载)

    • d1. Bootstrap ClassLoader --> 加载$JAVA_HOME中jre/lib/rt.ar里所有的class,由C++实现,不是ClassLoader子类
    • d2. Extension ClassLoader --> 加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
    • d3. App ClassLoader --> 加载classpath中指定的jar包及目录中class
    • d4. Custom ClassLoader --> 应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都自行实现了ClassLoader

b21. final --> 能修饰变量(局部变量、类变量、成员变量)、方法、类

  • c1. 修饰变量时: 变量变常量(赋值后不可以更改)
  • c2. 修饰属性时: 赋值只有两个机会 --> 1. 初始化属性时赋值 2. 构造方法中赋值
  • c3. 修饰方法时: 该方法不能被子类覆盖(用以保证操作的稳定性)
  • c4. 修饰类时: 该类不能被继承(注意: ;一个final类中的所有方法默认都是final的)

b22. abstract --> 能修饰类和方法

  • c1. 修饰类 时: 该抽象类不能构造对象(是用来被子类继承的)

  • c2. 修饰方法时: 称为抽象方法(只有方法定义,没有方法实现)

  • c3. 如果一个类有抽象方法,这个类必须为抽象类(不然实例化之后调用不动这个抽象方法)

  • c4. 单一个抽象类可以没有任何抽象方法

  • c5. 子类在继承抽象类时,必须实现该抽象类的每一个抽象方法(不然实例化后有些抽象方法调不动)

  • c6. 多态往往应用于抽象类中

  • c7. 举例:

      public abstract class super{
      	public abstract void method();//这里无大括号
      }
    
  • c8. 抽象类中可以写构造方法,作用是被子类的构造方法调用

  • c9. 非法的修饰符组合

    • d1. abstract 与 final -->继承与非继承互斥
    • d2. abstract 与 static -->继承的无静态多态性
    • d3. abstract 与 private -->私有的属性和方法无法被继承

    注意: 构造方法不存在继承,构造方法也不能被 abstract、final、static修饰

b23. interface --> 本质上它就是一个抽象类

  • c1. 一个文件只能写一个公开接口,接口名与文件名相同

  • c2. 接口是一种特殊的抽象类,所有属性都是公开静态常量,所有方法都是公开抽象方法,不允许定义构造方法

  • c3. 因为所有属性都是公开静态常量,所以public static final 可以省略

  • c4. 因为所有方法都是公开抽象方法,所以public abstract 可以省略

  • c5. 虽然接口的public是默认的,但实现类必须加上public

  • c6. 我们可以用关键字implements实现一个接口

  • c7. 接口实例:

      interface Ia{
      	public static final int A = 10;
      	public static final String S = "abc";
      	public abstract void method1();
      	public abstract int method2();
      }
    
  • c8. 用类实现接口,就要实现接口中定义的所有方法。而接口可以声明一个对象的引用,该引用可以调用编译时类型中定义的方法。

  • c9. 接口间也存在继承,关键字extends,而且允许多继承,用","隔开

      interface IC extends IA,IB{}
    
  • c10. 一个类在继承另外一个类的同时,还可以实现多个接口,实现了子接口就相当于实现了父接口

      public class Dog extends Animal implements IA, IB{}
    
  • c11. 接口的作用:

    • d1. 实现多继承(对同类事物的共性做一个再抽象,通过接口实现的多继承不会破坏类之间树状关系的简单性)
    • d2. 标准(一个接口是一个标准,可以把标准的制定者,标准的使用者和标准的实现者分离开。用以实现使用者和实现者的弱耦合,接口是java中最重要的解耦合工具)
    • d3. 通过接口可以屏蔽不同实现类的差异,把接口的一个实现替换成另外一个实现的时候,对上层代码在结构上没有影响
    • d4. 增加了程序的可扩展性
  • c12. 接口回调 --> 先有接口的使用者,后有接口的实现者,把实现者传给使用者,使用者通过接口调用实现者方法

b24. 如果一个类不写extends什么,那么将被默认为Object的直接子类(Object是所有类的父类)

b25. Java垃圾回收机制

本质上就是将不再使用的对象进行回收
jVM收集策略: 最少收集(万不得已才收集)

  • c1. 哪些对象不再使用? --> 不再被引用的对象(判定方法如下)

    • 老方法 --> 引用计数器: 维护一张列表,多一个引用加一,少一个引用减一,结果为0的收集
    • 新方法 --> 跟踪收集器: 对象引用递归遍历,找不到引用的就收集
  • c2. 如何回收?
    算法很多: 1.标记清除算法 2.复制算法 3.分代收集算法(G1在用)
    收集器种类很多, JDK1.7开始用G1收集器(多线程并且能充分利用多CPU、多核环境)

    • d1. 本质上就是分代收集
    • d2. 内存结构如下:
      • 持久代: 被JVM来存放方法区,而方法区存放了类信息、静态变量、常量、和方法信息。对持久代的回收 --> 废弃常量和无用的类
      • 年老代:
        1. 内存是新生代的2倍
        2. 经历了N次垃圾回收后仍然存活的对象
        3. 内存满时触发Full GC
      • 新生代:
        1. 大部分对象在Eden区生成
        2. Minor GC 过程(注:下面移动的都是标记为存活的对象):
          n1. 将eden区对象复制到survivor0区,然后清空eden区
          n2. 当survivor0区也存放满了时,将eden区和survivor0区存活对象复制到survivor1区,然后清空eden区和survivor0区
          n3. 此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复
          n4. 当survivor1区不足以存放eden和survivor0的存活对象时,就将survivor1区存活对象直接存放到老年代
  • c3. finalize() --> 在对象垃圾回收时调用finalize方法 (Object类下)

  • c4. System.gc() --> 唤起垃圾收集

b26. Hashset、Hashmap、Hashtable与hashcode()和equals()的密切关系

  • c1. equals()和hashcode()必须遵循的规则:

    • d1. equals()相等的两个对象必须hashcode()也相等
    • d2. 如果两个对象的hashCode相等,它们并不一定equals()相等

    根据如上规则最终推导出如下结论:

    • e1. hashcode()不等,一定能推出equals()也不等
    • e2. hashcode()相等,equals()可能相等,也可能不等
  • c2. Hash类集合的特点是,不允许出现重复对象。(如何做到?)

    • d1. 判断两个对象的hashCode是否相等,如果不相等,认为两个对象也不相等,如果相等,转入d2
    • d2. 判断两个对象用equals运算是否相等如果不相等,认为两个对象也不相等如果相等,认为两个对象相等
  • c3. Object默认的equals()比较的是对象地址,默认的hashCode()返回的也是对象地址

b27. 内部类(成员内部类、静态内部类、局部内部类、匿名内部类)

内部类的作用:

  1. 不破坏封装的情况下访问另外一个类的私有成员
  2. 把接口公开,但是把接口的实现类作为内部类隐藏起来,强制弱耦合
  3. 接口+内部类才可以实现多继承
  • c1.成员内部类
    • d1. 可以访问外部类的私有成员变量

    • d2. 构造成员内部类对象必须先构造外部类对象,通过外部类对象.new构造内部类对象

    • d3. 成员内部类不能是静态成员

        public class MemberOuter {
        	private int num = 3;
        	private String name = "somchai";
        	public class Inner{
        		String myInner = "myInner";		
        		String innerMethod(){
        			name = "inner hehe";
        			return name;
        		}
        	}	
        
        public static void main(String[] args) {
        	MemberOuter outer = new MemberOuter();
        	Inner inner = outer.new Inner();
        		System.out.println(inner.innerMethod());
        	}
        }
      
  • c2. 静态内部类
    • d1. 只能访问外部类的静态成员(包括私有)

    • d2. 构造静态内部类对象,可以直接构造不需要外部类对象

        public class StaticOuter {
        	private static String outName = "abc";
        	public static class Inner{
        		public void runTime(){
        			System.out.println(outName);
        		}
        	}
        	
        	public static void main(String[] args) {
        		StaticOuter.Inner inner = new StaticOuter.Inner();
        		inner.runTime();
        	}
        }	
      
  • c3. 局部内部类
    • d1. 定义在方法内部,有效范围和局部变量相同(代码块内部)

    • d2. 不仅可以访问外部类的私有属性,而且可以访问外部类的局部变量,但是要求被访问的局部变量是final的

        public class PartOuter {
        	public static Runnable getMe(){
        		final int a = 10;
        		class PartInner implements Runnable{
        			@Override
        			public void run() {
        				System.out.println("**********runOver***********" + a );
        			}
        		}
        		return new PartInner();
        	}
        	
        	public static void main(String[] args) {
        		new Thread(PartOuter.getMe()).start();
        	}
        }
      
  • c4. 匿名内部
    • d1. 它是一个特殊的局部内部类,定义这个类的目的是继承某一个类或者实现某一个接口

    • d2. 用一个隐含的没有名字的类继承一个类或者实现一个接口,同时构造出一个对象

    • d3. 匿名内部类无法定义构造方法

        public class NoNameOuter2 {
        	public static void main(String[] args) {
        		new Thread(new Runnable() {
        			@Override
        			public void run() {
        				System.out.println("*****run no name class*****");
        			}
        		}).start();
        	}
        }
      

b28. 无穷大

1.0/0 不会有异常,因为结果为double,double有一个常量Infinity代表无穷大,-Infinity代表无穷小

b29. 异常

  • c1. RuntimeException(不可查异常)
    • 这些异常一般是由程序逻辑错误引起的,应该从逻辑角度尽可能避免
    • 可以不处理(交给JVM处理)
    • 比如 NullPointerException
  • c2. 非RuntimeException(可查异常)
    • 无法避免的异常(一定会发生)
    • 必须处理(try块或throws)
    • 比如 IOException、SQLException以及用户自定义的Exception
  • c3. return语句先执行,finally语句后执行,return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。
  • c4. 子类的覆盖方法不能比父类的被覆盖方法抛出更多的异常
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值