1、Eclipse常用快捷键
alt+shift+r | 批量修改 |
ctrl+shift+f | 代码格式化 |
ctrl+shift+o | import 类 去掉未使用的类 等等 |
ctrl+shift+c | 快速注释 |
ctrl+shift+x | 小写转换为大写 |
ctrl+shift+y | 大写转换为小写 |
ctrl+1 | 快速解决办法提示 |
alt+shift+s | 默认方法快速生成 |
alt+shift+j | javadoc文档快速生成 |
2、控制台输入
从控制台输入数据,需要用到Scanner类
注意:使用Scanner类,需要import包:
import java.util.Scanner;
使用流程:
// 首先,创建Scanner对象
Scanner scanner = new Scanner(System.in);
// 然后,利用Scanner对象获取相应的数据,如:↓ ↓ ↓
int a = scanner.nextInt(); // 获取控制体输入的整数
示例:
/*
* 使用Scanner读取整数
*/
import java.util.Scanner;
public class ScannerTest{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
System.out.println("从控制台输入的第一个整数:" + a);
int b = scanner.nextInt();
System.out.println("从控制台输入的第二个整数:" + b);
}
}
/*
* 使用Scanner读取浮点数
*/
import java.util.Scanner;
public class ScannerTest{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
float a = scanner.nextFloat();
System.out.println("从控制台输入的是浮点数:" + a);
}
}
/*
* 使用Scanner读取字符串
*/
import java.util.Scanner;
public class ScannerTest{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String a = scanner.nextLine();
System.out.println("从控制台输入的是字符串:" + a);
}
}
/*
* 使用Scanner读取整数后接着读取字符串
*/
import java.util.Scanner;
public class ScannerTest{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
System.out.println("从控制台输入的整数是:" + a);
String str = scanner.nextLine();
System.out.println("从控制台输入的字符串是:" + str);
}
}
3、数组排序算法:直接选择法和冒泡法
(1)、直接选择法
直接选择法排序的思路是:
把第一个元素和后面所有的元素进行比较,只要比第一个元素小的,就和第一个元素互换位置 ,以此找到最小的元素
比较完后,第一位就是最小的
然后再把第二个元素和后面所有的元素进行比较,只要比第二个元素小的,就和第二个元素 互换位置,以此找到第二小的元素
比较完后,第二位就是第二小的
以此类推
public class SortTest {
public static void main(String[] args) {
SortTest test = new SortTest();
int[] a = new int[]{18,62,68,82,65,9};
a = test.sort(a);
for (int i : a) {
System.out.print(i + "\t");
}
}
public int[] sort(int[] a) {
// 从第一个元素开始依次比较,将这些元素暂且称为原点元素
for (int i = 0; i < a.length-1; i++) {
// 从原点元素的下一个元素开始,依次与原点元素进行比较,如果有元素比原点元素小,那么与原点元素互换
for (int j = i+1; j < a.length; j++) {
if (a[j] < a[i]) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
return a;
}
}
输出结果为:
(2)、冒泡法
冒泡法排序的思路是:
第一步:从第一个元素开始,把相邻两个元素进行比较,如果发现前者比后者大,就把大的数据交换在后面,循环比较完毕后,最后一位就是最大的
第二步: 再来一次,只不过不用比较最后一位
以此类推
public class SortTest {
public static void main(String[] args) {
SortTest test = new SortTest();
int[] a = new int[]{18,62,68,82,65,9};
a = test.sort(a);
for (int i : a) {
System.out.print(i + "\t");
}
}
public int[] sort(int[] a) {
// 从1开始,有n个元素,就要比较n-1趟,每比较一趟,确认一个最大/次大数
for (int i = 1; i < a.length; i++) {
// 从第一个元素开始,直到(总数-减去已确认最大/次大数的数量)的前一个元素,与后一个元素进行比较,大的放后边
for (int j = 0; j < a.length-i; j++) {
if (a[j] > a[j+1]) {
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
return a;
}
}
输出结果为:
4、针对数组的工具类——Arrays
注意:使用Arrays类,需要import包:
import java.util.Arrays;
Arrays工具类的方法:
方法名 | 功能 |
copyOfRange | 数组复制 |
toString() | 转换为字符串 |
sort | 排序 |
binarySearch | 搜索 |
equals | 判断是否相同 |
fill | 填充 |
import java.util.Arrays;
public class ArraysTest {
public static void main(String[] args) {
int a[] = new int[] { 18, 62, 68, 82, 65, 9 };
System.out.print("原数组为:");
for (int i : a) {
System.out.print(i + " ");
}
System.out.println();
// *********************复制数组**********************
System.out.println("*********************复制数组**********************");
// copyOfRange(int[] original, int from, int to)
// 第一个参数表示源数组
// 第二个参数表示开始位置(取得到)
// 第三个参数表示结束位置(取不到)
int[] b = Arrays.copyOfRange(a, 0, 3);
System.out.print("复制的数组:");
for (int i = 0; i < b.length; i++) {
System.out.print(b[i] + " ");
}
System.out.println();
// *********************转换为字符串**********************
System.out.println("*********************转换为字符串**********************");
// toString(int[] a)
// 参数a代表源数组
String str = Arrays.toString(a);
System.out.println("转换为字符串后的形式:" + str);
// *********************排序**********************
System.out.println("*********************排序**********************");
// sort(int[] a)
// 参数a代表源数组
System.out.println("排序前:");
System.out.println(Arrays.toString(a));
Arrays.sort(a);
System.out.println("排序后:");
System.out.println(Arrays.toString(a));
// *********************搜索元素的位置**********************
System.out.println("*********************搜索元素的位置**********************");
// binarySearch(int[] a, int key)
// 参数a代表源数组
// 参数key代表要查找的元素
// 要注意的是:在查找前需要先对数组进行排序
Arrays.sort(a);
System.out.println("62的位置在:" + Arrays.binarySearch(a, 62));
// *********************判断是否相同**********************
System.out.println("*********************判断是否相同**********************");
// equals(int[] a,int[] b)
// 参数a和b分别代表要进行比较的两个数组
int x[] = new int[] { 18, 62, 68, 82, 65, 9 };
int y[] = new int[] { 18, 62, 68, 82, 65, 8 };
System.out.println("数组x为:" + Arrays.toString(x));
System.out.println("数组y为:" + Arrays.toString(y));
System.out.println("数组x和数组y进行比较的结果是:" + Arrays.equals(x, y));
// *********************填充**********************
System.out.println("*********************填充**********************");
// fill(int[] a,int val)
// 参数a代表源数组
// 参数val代表要填充的值
int c[] = new int[10];
System.out.println("填充前的c数组为:" + Arrays.toString(c));
Arrays.fill(c, 5);
System.out.println("填充后的c数组为:" + Arrays.toString(c));
}
}
输出结果为:
5、属性初始化
对象属性初始化的方法有3种:
(1)、声明该属性的时候初始化
(2)、构造方法中初始化
(3)、初始化块
public class AttrInitTest {
public String name = "name属性"; // 声明该属性的时候初始化
protected int hp;
private int maxHP;
{
maxHP = 200; // 初始化块
}
public AttrInitTest() {
hp = 100; // 构造方法中初始化
}
public static void main(String[] args) {
AttrInitTest test = new AttrInitTest();
System.out.println(test.name + "\t" + test.maxHP + "\t" + test.hp);
}
}
输出结果为:
类属性初始化的方法有2种:
(1)、声明该属性的时候初始化
(2)、静态初始化块
public class AttrInitTest {
public String name = "name属性"; // 声明该属性的时候初始化
protected int hp;
private int maxHP;
public static int itemCapacity=8; //声明的时候 初始化
public AttrInitTest(){
}
public static void main(String[] args) {
System.out.println(AttrInitTest.itemCapacity);
}
}
输出结果:
public class AttrInitTest {
public String name;
protected float hp;
float maxHP;
public static int itemCapacity; // 声明类属性
static {
itemCapacity = 6;// 静态初始化块 初始化
}
public AttrInitTest() {
}
public static void main(String[] args) {
System.out.println(AttrInitTest.itemCapacity);
}
}
输出结果:
【声明属性时初始化】、【构造方法中初始化】、【初始化块中初始化】 这3中初始化的顺序:
声明时初始化 → 初始化块中初始化 → 构造方法中初始化
6、单例模式
单例模式又叫做 Singleton模式,指的是 : 一个类,在一个JVM里,只有一个实例存在。也就是只能被实例化一次。
打个比方: 王者峡谷中的暗影主宰只有一个,所以主宰这个类只能被实例化一次
原理:【
单例模式的类只能被实例化一次,那么,就不能通过外部new的方式得到新的实例,
所以,我们需要将构造方法私有化;
但是,毕竟还要实例化一次的,那么,我们在类内声明一个静态属性,
使得这个静态属性指向实例化对象;
接下来,毕竟类设计出来就是要用的,那么,我们需要一个方法来将这个实例化对象,也就是已经指向这个实例的静态属性返回,
即返回实例;
】
综上,我们就总结出了单例模式的三元素:
【构造方法私有化、 静态属性指向实例、类方法 getInstance,返回静态属性,即唯一实例】
下面,来看以下代码示例:
饿汉式单例模式:
class Zhuzai{
// 私有化构造方法使得该类无法在外部通过new 进行实例化
private Zhuzai() {
}
// 准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个
private static Zhuzai zhuzai = new Zhuzai();
// public static 方法,提供给调用者获取类的唯一实例对象
public static Zhuzai getInstnce() {
return zhuzai;
}
}
public class SingletonTest {
public static void main(String[] args) {
Zhuzai zhuzai1 = Zhuzai.getInstnce(); // 新建一个主宰对象
Zhuzai zhuzai2 = Zhuzai.getInstnce(); // 再次新建一个主宰对象
// 分别输出两个主宰对象的地址
System.out.println(zhuzai1);
System.out.println(zhuzai2);
}
}
输出结果:
可以很明显的看出,这两个主宰对象其实是同一个,他们的地址都是一样的。
懒汉式单例模式:
class Zhuzai{
// 私有化构造方法使得该类无法在外部通过new 进行实例化
private Zhuzai() {
}
//准备一个类属性,用于指向一个实例化对象,但是暂时指向null
private static Zhuzai zhuzai;
// public static 方法,提供给调用者获取类的唯一实例对象
public static Zhuzai getInstnce() {
//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
if(null == zhuzai){
zhuzai = new Zhuzai();
}
//返回 instance指向的对象
return zhuzai;
}
}
public class SingletonTest {
public static void main(String[] args) {
Zhuzai zhuzai1 = Zhuzai.getInstnce(); // 新建一个主宰对象
Zhuzai zhuzai2 = Zhuzai.getInstnce(); // 再次新建一个主宰对象
// 分别输出两个主宰对象的地址
System.out.println(zhuzai1);
System.out.println(zhuzai2);
}
}
输出结果:
可以很明显的看出,这两个主宰对象其实是同一个,他们的地址都是一样的。
饿汉式和懒汉式的区别及应用场景:
饿汉式是立即加载的方式,无论是否会用到这个对象,都会加载。
如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。
懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量。
使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。
看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式。
注意:【这个是面试的时候经常会考的点,面试题通常的问法是: ↓ ↓ ↓ 】
什么是单例模式?
回答的时候,要答到三元素
1. 构造方法私有化
2. 静态属性指向实例
3. public static的 getInstance方法,返回第二步的静态属性
7、Java中的方法隐藏
隐藏与重写类似;
方法的 重写,是子类覆盖父类的对象方法 ;
而方法的 隐藏,是子类覆盖父类的类方法。
class Father{
public static void method() {
System.out.println("这是父类的类方法!");
}
}
public class MethodHiddenTest extends Father {
public static void method() {
System.out.println("这是子类的类方法!");
}
public static void main(String[] args) {
Father.method(); // 调用父类的method方法
MethodHiddenTest.method(); // 调用子类的method方法
}
}
输出结果:
子类的method方法将父类的method方法隐藏掉了,调用时直接调用的是子类的method方法。
8、Java 的修饰符 final
fianl 修饰类,表示该类为最终类,不能再被继承;
final 修饰方法,表示在其子类中,该方法不能被重写;
final 修饰基本类型变量,表示该变量只有一次赋值机会 ;
final 修饰引用,表示该引用只有1次指向对象的机会,但是该对象的属性值依旧可以被修改。
9、接口的默认方法
默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法。
默认方法需要声明为default
interface TestInterface{
default void defaultMethod() {
System.out.println("这是默认方法!");
}
}
public class DefaultMethodTest implements TestInterface {
public static void main(String[] args) {
TestInterface test = new DefaultMethodTest();
test.defaultMethod();
}
}
输出结果:
10、Java Math 类常用数学方法记录
方法名 | 功能 |
round | 四舍五入 |
random | 得到一个0-1之间的随机浮点数(取不到1) |
random()* 10 | 得到一个0-10之间的随机整数 (取不到10) |
sqrt | 开方 |
pow(2,4) | 2的4次方 |
11、字符串的格式化输出
printf 和 format 可以达到格式化输出字符串的效果,其作用效果一样,源码层次上是 printf 中直接调用了 format ;
public class FormatStringTest {
public static void main(String[] args) {
String name = "盖伦";
int kill = 8;
String title = "超神";
String sentenceFormat = "%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
// 使用printf格式化输出
System.out.printf(sentenceFormat, name, kill, title);
// 使用format格式化输出
System.out.format(sentenceFormat, name, kill, title);
}
}
格式 | 含义 |
%s | 字符串 |
%d | 数字 |
%n | 换行 |
12、字符串内容比较(忽略大小写)
equalsIgnoreCase(String anotherString)
13、StringBuffer
StringBuffer是可变长的字符串;
StringBuffer 的常用方法:
方法名 | 功能 |
append( "new String" ) | 在原有字符串后面追加 |
delete( 4 , 10 ) | 删除4-10之间的字符(包括4,不包括10) |
insert( 4 , "there " ) | 在4这个位置插入 there |
reverse() | 反转 |
length() | 内容长度 |
capacity() | 总空间 |
为什么StringBuffer可以变长?
和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度。
比如说new StringBuffer("the"),其内部的字符数组的长度,是16,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了16,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中,看上去 数组长度就变长了 .
length: “the”的长度 3
capacity: 分配的总空间 16
StringBuffer 和 String 的性能比较:
14、日期类 Date
注意:使用日期类 Date ,需要导入相应的包:
import java.util.Date;
在计算机里,日期类型会用一个数字来代替,其代表的是距离1970年1月1日8时0分0秒过去了多少毫秒。
0就代表Java中的时间原点,其对应的日期是1970年1月1日 8点0分0秒 。
所有的日期,都是以为这个0点为基准,每过一毫秒,就+1。
创建日期对象:
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
Date test = new Date();
System.out.println(test);
}
}
输出结果:
Date 对象的常用方法有:
方法名 | 功能 |
getTime() | 得到一个long型的整数 这个整数代表 从1970.1.1 08:00:00:000 开始 每经历一毫秒,增加1 |
currentTimeMillis() | 当前日期的毫秒数 |
15、日期格式化
要格式化日期,需要用到 SimpleDateFormat 日期格式化类
注意,需要导入相应的包:
import java.text.SimpleDateFormat;
格式化的格式:
格式 | 含义 |
y | 代表年 |
M | 代表月 |
d | 代表日 |
H | 代表24进制的小时 |
h | 代表12进制的小时 |
m | 代表分钟 |
s | 代表秒 |
S | 代表毫秒 |
转化的方法如下:
方法名 | 功能 |
format | 日期转字符串 |
parse | 字符串转日期 |
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatTest {
public static void main(String[] args) {
// y 代表年
// M 代表月
// d 代表日
// H 代表24进制的小时
// h 代表12进制的小时
// m 代表分钟
// s 代表秒
// S 代表毫秒
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
Date d = new Date();
String str = sdf.format(d);
System.out.println("当前时间通过 yyyy-MM-dd HH:mm:ss SSS 格式化后的输出: " + str);
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String str1 = "2016/1/5 12:12:12";
try {
Date d1 = sdf1.parse(str1);
System.out.printf("字符串 %s 通过格式 yyyy/MM/dd HH:mm:ss %n转换为日期对象: %s", str, d.toString());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
输出结果:
16、日历类 Calendar
注意:要使用Calendar 包,需要导入相应的包:
import java.util.Calendar;
Calendar类即日历类,常用于进行“翻日历”,比如下个月的今天是多久。
Calendar与Date进行转换:
采用单例模式获取日历对象Calendar.getInstance();
import java.util.Calendar;
import java.util.Date;
public class CalendarTest {
public static void main(String[] args) {
//采用单例模式获取日历对象Calendar.getInstance();
Calendar c = Calendar.getInstance();
//通过日历对象得到日期对象
Date d = c.getTime();
System.out.println(d);
Date d2 = new Date(0);
c.setTime(d2); //把这个日历,调成日期 : 1970.1.1 08:00:00
System.out.println(c.getTime());
}
}
输出结果:
Calendar 类翻日历的方法:
方法名 | 功能 |
add(int file, int amount) | 在原日期上增加年/月/日(field 代表是年还是月还是日等) |
set | 直接设置年/月/日 |
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class CalendarTest {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
Date now = c.getTime();
// 当前日期
System.out.println("当前日期:\t\t" + format(c.getTime()));
// 下个月的今天
c.setTime(now);
c.add(Calendar.MONTH, 1);
System.out.println("下个月的今天:\t" + format(c.getTime()));
// 去年的今天
c.setTime(now);
c.add(Calendar.YEAR, -1);
System.out.println("去年的今天:\t\t" + format(c.getTime()));
// 上个月的第三天
c.setTime(now);
c.add(Calendar.MONTH, -1);
c.set(Calendar.DATE, 3);
System.out.println("上个月的第三天:\t" + format(c.getTime()));
}
private static String format(Date time) {
return sdf.format(time);
}
}
输出结果:
17、基本数据类型的长度及范围
类型 | 缺省值 | 长度 | 范围 |
byte | 0 | 8位 | -128~127 |
short | 0 | 16位 | -32,768~32,767 |
int | 0 | 32位 | -2,147,483,648~2,147,483,647 |
long | 0 | 64位 | -9,223,372,036,854,775,808~9,223,372,036,854,775,807 |
float | 0.0 | 32位 | 3.4E-038~3.4E+038 |
double | 0.0 | 64位 | 1.7E-308~1.7E+308 |
char | 无 | 16位 | 一个字符 |
boolean | false | 1位 | true/false |