JAVA基础——谜之一笑

又到了面试环节,重温一下最初学习的历程吧!

  1. java程序启动之谜:加载顺序。
    静态类+静态代码块+构造方法

  2. java关键字之谜:重点难点
    static+this+final+throw+throws+try catch finally+native+synchronized+super+break+continue+instanceof+abstract

  3. java多线程之谜:各种方法
    start+join+sleep+

  4. java文件操作IO之谜:各种流
    字节流+字符流+缓冲流

  5. java异常处理之谜:自定义异常
    定义+处理+使用

  6. java网络编程之socket之谜:CS分明
    单次通讯+循环通讯+多线程通讯

  7. java字符类之谜:字符串操作出神入化
    String+StringBuild+StringBuffer
    正则表达式

  8. java注解之谜:
    原生注解+常用注解+自定义注解

  9. java权限之谜
    public+protect+默认+private

  10. java内部类之谜

  11. java集合之谜:
    Collection+Map

  12. java设计模式之谜:创建型+行为型+结构型
    策略模式+访问者模式+装饰模式+适配器模式+工厂模式+单例模式+代理模式

  13. java数据库操作之谜
    JDBC

  14. java枚举类之谜:活学活用
    定义工具类

  15. java排序算法之谜
    冒泡+插入+简单+快速+

一、数据类型

数据类型分类
Java的数据类型分为两大类:
基本数据类型:包括 整数 、 浮点数 、 字符 、 布尔 。
引用数据类型:包括 类 、 数组 、 接口 。
基本数据类型 四类八种基本数据类型:

 数据类型 	关键字 	内存占用 	取值范围
 字节型 		byte 	1个字节 		-128~127 
 短整型 		short 	2个字节 		-32768~32767 
 整型 		int(默认) 4个字节 -231次方~231次方-1 
 长整型 		long 	8个字节 		-263次方~263次方-1 
 单精度浮点数 float 4个字节		 1.4013E-45~3.4028E+38 
 双精度浮点数 double(默认) 8个字节 	4.9E-324~1.7977E+308 
 字符型 		char 	2个字节 		0-65535 
 布尔类型 	boolean 1个字节 		truefalse

二、运算符

2.1 算数运算符
在这里插入图片描述
2.2 赋值运算符
在这里插入图片描述
2.3 比较运算符
在这里插入图片描述
2.4 逻辑运算符
在这里插入图片描述
2.5 三元运算符
在这里插入图片描述
2.6 补充
2.6.1 +=符号
下面的程序有问题吗?

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.
如果是s = s + 1;的话就会报错.
2.6.2 常量和变量的运算
下面的程序有问题吗?

public static void main(String[] args){
 	byte b1=1; byte b2=2;
 	byte b3=1 + 2;
  	byte b4=b1 + b2;
	System.out.println(b3);
	System.out.println(b4);
}

分析: b3 = 1 + 2 , 1 和 2 是常量,为固定不变的数据,在编译的时候(编译器javac),已经确定了 1+2 的结果并没 有超过byte类型的取值范围,可以赋值给变量 b3 ,因此 b3=1 + 2 是正确的。
反之, b4 = b2 + b3 , b2 和 b3 是变量,变量的值是可能变化的,在编译的时候,编译器javac不确定b2+b3的结果是什 么,因此会将结果以int类型进行处理,所以int类型不能赋值给byte类型,因此编译失败。

在给变量进行赋值的时候,如果右侧的表达式当中全都是常量,没有任何变量,
那么编译器javac将会直接将若干个常量表达式计算得到结果。
short result = 5 + 8; // 等号右边全都是常量,没有任何变量参与运算
编译之后,得到的.class字节码文件当中相当于【直接就是】:
short result = 13;
右侧的常量结果数值,没有超过左侧范围,所以正确。

这称为“编译器的常量优化”。

但是注意:一旦表达式当中有变量参与,那么就不能进行这种优化了。

三、常用API

3.1 Scanner 类
Scanner使用步骤
a. 查看类java.util.Scanner :该类需要import导入后使用。
b. 查看构造方法 public Scanner(InputStream source) : 构造一个新的 Scanner ,它生成的值是从指定的输入流扫描的。
c. 查看成员方法 public int nextInt() :将输入信息的下一个标记扫描为一个 int 值。
d. 使用Scanner类,完成接收键盘录入数据的操作,代码如下:

//1. 导包 
import java.util.Scanner;
public class Demo01_Scanner {
	public static void main(String[] args) { 
		//2. 创建键盘录入数据的对象 
		Scanner sc = new Scanner(System.in); 
		//3. 接收数据 
		System.out.println("请录入一个整数:"); 
		int i = sc.nextInt(); 
		//4. 输出数据 
		System.out.println("i:"+i); 
		
		System.out.println("请输入一个字符串数据:"); 
		String s = sc.nextLine();
	} 
}


3.2 ArrayList类
到目前为止,我们想存储对象数据,选择的容器,只有对象数组。而数组的长度是固定的,无法适应数据变化的需 求。为了解决这个问题,Java提供了另一个容器 java.util.ArrayList 集合类,让我们可以更便捷的存储和操作对 象数据。
java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素。
ArrayList对象不能存储基本类型,只能存储引用类型的数据。类似 不能写,但是存储基本数据类型对应的 包装类型是可以的。所以,想要存储基本类型数据, <> 中的数据类型,必须转换后才能编写,转换写法如下:

3.3 Arrays类
java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来 非常简单。
public static String toString(int[] a) :返回指定数组内容的字符串表示形式
public static void sort(int[] a) :排序,默认升序
3.4 static关键字
它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。
静态方法调用的注意事项
静态方法可以直接访问类变量和静态方法。 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。 静态方法中,不能使用this关键字。
小贴士:静态方法只能访问静态成员
3.5 String类tips
a. 对于引用类型来说,==进行的是地址值的比较
b. 双引号直接写得字符串在常量池中,new\de不在池当中

String类与StringBuilder类的比较。
如何理解String创建后不能更改?
确实,Java中的String类型确实是不允许改变其内容的,String类型的对象一旦建立,将在堆内存当中占据一个固定的内存空间,String类型的对象无法改变。
但是你在运算的时候又发现,你定义的String类型的s变量又是可以进行连接的,如"abc"+“def"最终得到的s的值是"abcdef”,这似乎看着String类型的对象又是可以改变的,这是自相矛盾吗?
其实,String对象不允许改变内容是正确的,但是可以改变定义的String类型的变量指向,你定义的String s其实是一个指向String对象的指针,如果不存在对象就为null。
如果你定义了:
String s=“abc”;
那么将创建一个内容为"abc"的String对象,并且s指向这个对象。
一旦s=s+123+new Date()这样的操作,那么将创建一个新的String对象来存放新的内容,原先的对象依旧在内存中,但是s不在指向它,那么这个对象就会成为垃圾内存,在某一个特定的时刻有Java虚拟机回收。
如果希望存放的String可以调整大小,而不是创建新的内存来存放新的对象,可以使用StringBuffer这个类来存放。这个内存可以调整大小。而不会抛弃。

四、继承

4.1 class 子类 extends 父类
4.2 方法重写(覆盖)
如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效 果,也称为重写或者复写。声明不变,重新实现。
4.3 super和this
super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)

4.4 只支持单继承

五、抽象类

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有 意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法 的类就是抽象类。
抽象方法
使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象类
如果一个类包含抽象方法,那么该类必须是抽象类。
注意要点tips

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象 类。

六、接口与多态

接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并 不是类,而是另外一种引用数据类型。
接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做 是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象 类。
6.1 定义格式

public interface 接口名称 { 
	// 抽象方法 
	// 默认方法 
	// 静态方法 
	// 私有方法 
}

含有抽象方法
抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。

public interface InterFaceName { 
	public abstract void method();
}

含有默认方法和静态方法
默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。
静态方法:使用 static 修饰,供接口直接调用。

public interface InterFaceName { 
	public default void method() { 
		// 执行语句 
	}
	public static void method2() { 
		// 执行语句 
	}
}

含有私有方法和私有静态方法
私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用。

public interface InterFaceName { 
	private void method() { 
		// 执行语句 
	} 
}

6.2 注意事项tips
非抽象子类实现接口:

  1. 抽象方法,必须重写接口中所有抽象方法。
  2. 默认方法,可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。
  3. 静态方法,静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用
  4. 私有方法,只有默认方法可以调用。 私有静态方法:默认方法和静态方法可以调用。 如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法 去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。
  5. 一个类可以实现多个接口,必须实现所有抽象方法
  6. 实现多个接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的(多个接口都有该默认方法),必须重写一次。
  7. 实现多个接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。
  8. 优先级的问题,当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。
  9. 接口的多继承,一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用 extends 关键字,子接口继 承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。
  10. 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
  11. 接口中,没有构造方法,不能创建对象。
  12. 接口中,没有静态代码块。

多态是继封装、继承之后,面向对象的第三大特性。

  • 多态: 是指同一行为,具有多个不同表现形式。
  • .多态的体现,1.继承或者实现【二选一】 2. 方法的重写【意义体现:不重写,无意义】 3. 父类引用指向子类对象【格式体现】
父类类型 变量名 = new 子类对象; 
变量名.方法名();
//父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
  • 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写 后方法。
    引用类型转换
    多态的转型分为向上转型与向下转型两种
  • 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。 当父类引用指向一个子类对象时,便是向上转型。
  • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

七、final关键字

final: 不可改变。可以用于修饰类、方法和变量。
类:被修饰的类,不能被继承。
方法:被修饰的方法,不能被重写。
变量:被修饰的变量,不能被重新赋值。

基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。
引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的 修改。

成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:
显示初始化;

public class User { 
	final String USERNAME = "张三"; 
	private int age; 
}

构造方法初始化。

public class User { 
	final String USERNAME ; 
	private int age; 
	public User(String username, int age) { 
		this.USERNAME = username; 
		this.age = age; 
	} 
}

八、权限修饰符

在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限。
public:公共的。
protected:受保护的
default:默认的
private:私有的
在这里插入图片描述
可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:
成员变量使用 private ,隐藏细节。
构造方法使用 public ,方便创建对象。
成员方法使用 public ,方便调用方法。
小贴士:不加权限修饰符,其访问能力与default修饰符相同

九、内部类

内部类:将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
成员内部类 :定义在类中方法外的类。
访问特点:内部类可以直接访问外部类的成员,包括私有成员。 外部类要访问内部类的成员,必须要建立内部类的对象。

外部类名.内部类名 对象名 = new 外部类型().new 内部类型()

匿名内部类 :是内部类的简化写法。它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象。 开发中,最常用到的内部类就是匿名内部类了。
以接口举例,当你使用一个接口时,似乎得做如下几步操作, 1. 定义子类 2. 重写接口中的方法 3. 创建子类对象 4. 调用重写后的方法
匿名内部类必须继承一个父类或者实现一个父接口。前提,匿名内部类必须继承一个父类或者实现一个父接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值