一、用户交互
Scanner对象
java.util.Scanner 是 Java5 的新特征,我们可以通过Scanner 类来获取用户的输入,它的基本语法为:
Scanner s = new Scanner(System.in);
其中举例两种:next() 与 nextLine()
next()
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
所以,next() 不能得到带有空格的字符串。
nextLine()
- 以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
所以,nextLine() 可以获得空白。
用完Scanner一定要关闭掉节省资源:
scanner.close();
二、结构
1.顺序结构
Java的基本结构,也是最简单的算法结构。
2. 选择结构
-
if 选择结构:其中有多个if,则else与最近的if相配对
-
switch case选择结构:
- switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。
- switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
- 当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。
- switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。
- switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断。如果当前匹配成功的 case 语句块没有 break 语句,则从当前 case 开始,后续所有 case 的值都会输出,如果后续的 case 语句块有 break 语句则会跳出判断。
switch (expression){
case value :
...//执行语句
break;//防止向下穿透
case value :
...//执行语句
break;//防止向下穿透
default :
//其他情况
}
3. 循环结构
Java中有三种主要的循环结构:
- while 循环 : 条件为真,则会一直循环下去;为假则不执行
- do…while 循环 : 条件为真,则会一直执行do的内容;为假则执行一次。此循环最少执行一次
- for 循环 :
最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。接着检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。执行一次循环后,更新循环控制变量。再次检测布尔表达式。重复
4.break和continue
- break:用于任何循环体中的主体部分,强行退出循环,不执行循环中剩余的部分
- continue:用于循环语句中,终止某次循环,跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
三、方法
一般情况下,定义一个方法包含以下语法:
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
方法包含一个方法头和一个方法体。
一个方法的有这几个部分部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 方法体:方法体包含具体的语句,定义该方法的功能。
方法的重载:
(1)方法名称必须相同
(2)参数列表必须不同(个数、类型、参数排序顺序不同等)
(3)方法的返回值可以相同也可以不同
(4)只有返回值类型不同不足以成为方法的重载
可变参数
在方法声明中,在指定参数类型后加一个省略号(…) 。
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
例:
public static void main(String[] args) {
//调用可变参数的方法
printMax(1,23,46,8,2,56,13,852);
printMax(new double[]{2,452,6,5,23,5,2,3});
}
//输出最大值
public static void printMax(double...numbers){
if(numbers.length==0){
System.out.println("没有找到数");
return;
}
double result=numbers[0];
//排序
for (int i=1;i<numbers.length;i++){
if (numbers[i]>result){
result=numbers[i];
}
}
System.out.println("最大值为"+result);
}
四、数组
1. 什么是数组
- 数组是想用类型数据的有序集合
- 数组描述的是相同了的若干个数据,按照一定的先后次序排列组合而成
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问到它们
2. 数组的声明和创建
- 首先必须声明数组变量,才能在程序中使用数组
dataType[] arrayRefVar; // 首选的方法
dataType arrayRefVar[]; // 效果相同,但不是首选方法
- Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
- 数组的元素是通过索引访问的,数组索引从0开始
- 获取数组长度
arrays.length
3. 数组的三种初始化
- 静态初始化
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
- 动态初始化
int[] a = new int[2];
a[0]=1;
a[1]=2;
- 数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量的方式被隐藏式初始化
4.多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组,例如:
String[][] str = new String[3][4];
5.Arrays 类
java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
它具有以下功能:
- 给数组赋值:通过 fill 方法。
public static void fill(int[] a, int val)
//将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。
//a - 要填充的数组
//val - 要存储在数组的所有元素中的值
- 对数组排序:通过 sort 方法,按升序。
public static void sort(Object[] a)
//对指定对象数组根据其元素的自然顺序进行升序排列。
- 比较数组:通过 equals 方法比较数组中元
public static boolean equals(long[] a, long[] a2)
//如果两个指定的 long 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
public static int binarySearch(Object[] a, Object key)
用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。如果查找值包含在数组中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。
import java.util.Arrays;
public class Demo02 {
public static void main(String[] args) {
int[] a = {56,1,48,64,2,6,78,81,};
System.out.println(Arrays.toString(a));//[56, 1, 48, 64, 2, 6, 78, 81]
Arrays.sort(a);
System.out.println(Arrays.toString(a));//[1, 2, 6, 48, 56, 64, 78, 81]
Arrays.fill(a,2,4,0);//在2<=x<4之间填充0
System.out.println(Arrays.toString(a));//[1, 2, 0, 48, 56, 64, 78, 81]
}
}
6.冒泡排序和稀疏矩阵
public class Demo01 {
public static void main(String[] args) {
int[] a={1,265,254,951,5,25,3852,};
System.out.println(Arrays.toString(a));
sort(a);
System.out.println(Arrays.toString(a));
}
public static int[] sort(int[] a){
//外层循环,判断走多少次
for (int i=0;i<a.length-1;i++){
//内层循环,两两比较
for (int j=0;j< a.length-1-i;j++){
if (a[j]>a[j+1]){
int temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
}
return a;
}
}
public class Demo04 {
public static void main(String[] args) {
int[][] a1=new int[5][5];//定义数组
a1[1][1]=1;
a1[2][2]=2;//赋值
System.out.println("原始数组:");
//遍历a1
for(int[] a:a1){
for (int b:a){
System.out.print(b+" ");
}
System.out.println();
}
//创建稀疏数组
System.out.println("稀疏数组为:");
//判断数组中非0元的个数数
int sum=0;
for (int i=0;i< 5;i++){
for (int j=0;j<5;j++){
if (a1[i][j]!=0){
sum++;
}
}
}
//稀疏数组的第0行
int[][] a2=new int[sum+1][3];
a2[0][0]=5;
a2[0][1]=5;
a2[0][2]=sum;
//稀疏数组的其他行
int count=0;
for (int i=0;i<a1.length;i++){
for (int j=0;j<a1[i].length;j++){
if (a1[i][j]!=0){
count++;
a2[count][0]=i;
a2[count][1]=j;
a2[count][2]=a1[i][j];
}
}
}
//遍历稀疏数组
for(int[] a:a2){
for (int b:a){
System.out.print(b+" ");
}
System.out.println();
}
}
}
/*
结果:
原始数组:
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 0 0
0 0 0 0 0
稀疏数组:
5 5 2
1 1 1
2 2 2
*/
五、面对对象
三个要点:
- 面向对象思想:分类的思维模式,首选思考问题如何分类,再对分类好的各个问题进行单独的思考解决;适合处理复杂的问题。(面向过程思想:思考问题步骤清晰简单,适合处理一些较为简单的问题)
- 面向对象的本质:以类的方式组织代码,以对象的组织封装数据
- 面向对象的三大特性:封装、继承、多态
1.封装
在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点:
- 良好的封装能够减少耦合。
- 类内部的结构可以自由修改。
- 可以对成员变量进行更精确的控制。
- 隐藏信息,实现细节。
public class StudentPrivate {
private String name;
private int age;
private char sex;
public int getAge(){
return age;
}
public void setAge(int age){
if (age<0||age>130){
this.age=0;
}else {
this.age = age;
}
}
// alt+insert 快捷键
}
2. 继承
- 继承关系的俩个类,一个为子类(派生类),一个为父类(基类);子类继承父类使用关键字extends来表示
- java中只用单继承,没有多继承;即一个子类只能有一个父类,但一个父类可以有多个子类
- 在java中所有类都默认直接或间接继承object类
继承的特性:
- 子类拥有父类非 private 的属性、方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java 的继承是单继承,但是可以多重继承。
方法的重写:
- 需要有继承关系,子类重写父类
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小:public > project > default > private
- 抛出的异常:范围可以缩小,但不能扩大
- 重写时子类的方法和父类必须一致,方法体不同
3.多态
多态的优点:
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
多态存在的三个必要条件:
- 继承
- 重写
- 父类引用指向子类对象:Parent p = new Child();
4. 构造器
- 构造器,也称构造方法、构造函数。作用是构造出来一个类的实例,确保对象得到初始化。
根据有无参数,可分为无参构造 和有参构造。 - 构造器最大的用处就是在创建对象时执行初始化,当创建一个对象时,系统会为这个对象的实例进行默认的初始化。如果想改变这种默认的初始化,就可以通过自定义构造器来实现。
- 构造器可以用来在初始化对象时初始化数据成员,一个类可以有多个构造器。一个类的构造器的名称必须与该类的名称一致。要退出构造,可以使用返回语句“return;”
构造器的特性
- 与一般方法名不同的是,构造方法名必须和类名保持一致,并且没有返回值,甚至连void都没有。
- Java编译器会自动创建无参构造函数,因此在类中,无参构造即使没有,我们也可省略不写。实例化对象时无需赋值
- 倘若类中已存在有参构造函数,则编译器不再提供默认无参构造。实例化对象时需赋值,不然报错。
- 当类实例化一个对象时会自动调用构造方法。
- 不能被static、final、synchronized、abstract和native修饰。构造方法不能被子类继承
- 每个类可以有零个或多个构造方法.
注意: 无参构造器默认存在类中,无需定义;但当定义了有参构造之后,想要调用无参构造就必须定义无参构造器后才可调用
public class Person {
String name;
int age;
//有参构造器
public Person(String name,int age){
this.name=name;
this.age=age;
}
//无参构造器 默认为空,可以在里面初始化值
public Person(){
this.name = "zhang";
}
public void work(){
System.out.println(age+"岁的"+name+"在工作");
}
//构造器快捷键----alt+insert
}
public class Text {
public static void main(String[] args) {
//调用有参构造器
Person wang = new Person("wang",18); // wang
System.out.println(wang.name); // 18
System.out.println(wang.age); // 18岁的wang在工作
wang.work();
//调用无参构造器(类中默认存在,不用定义,但当存在有参构造器时,想要调用无参构造器就需要定义无参构造器)
Person person=new Person();
}
}
六、接口
- 定义接口类型--------interface
- 继承接口-------implements
- 抽象类只能实现单继承,接口可以实现多继承
- 接口不能被实例化,接口中没有构造方法
- 必要时需要重写接口中的方法
- 接口在所有定义的属性都是抽象的----public static final;接口在所有定义的方法都是抽象的----
public interface TimeService {
void timer();
}
public interface UserService {
//接口在所有定义的属性都是抽象的---public static final
int age=11;
//接口在所有定义的方法都是抽象的---public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//抽象类 static
//类 可以实现接口 implements
//实现了接口,需要重写接口中的方法
//接口可以实现多继承,抽象类只能实现单继承
public class Impl implements UserService,TimeService{
@Override
public void timer() {
}
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
七、内部类
- 成员内部类
public class Outer {
private int age=50;
public void outer(){
System.out.println("这是外部类");
}
public class Inter{
public void inter(){
System.out.println("这是内部类");
}
//可以访问外部类的私有属性
public int getAge(){
return age;
}
}
}
public class text {
public static void main(String[] args) {
//实例化外部类
Outer outer=new Outer();
outer.outer();
//通过内部类实例化外部类
Outer.Inter inter=outer.new Inter();
inter.inter();
System.out.println(inter.getAge());
}
}
- 静态内部类
public class Outer {
private int age=50;
public void outer(){
System.out.println("这是外部类");
}
// 静态内部类
public static class Inter{
public void inter(){
System.out.println("这是静态内部类");
}
}
}
- 局部内部类
public class Outer {
public void method(){
//局部内部类
class Inter{
}
}
}
- 匿名内部类
public class App {
public static void main(String[] args) {
//没有名字初始化类,不用讲实例化保存到变量中
//匿名类
new Apple().eat();
new UserService(){
@Override
public void hello() {
}
};
}
}
//一个java文件只能有一个public class,但是可以有多个class
class Apple{
public void eat(){
System.out.println("eat");
}
}
interface UserService{
void hello();
}
八、异常
处理异常的五个关键字:
try、catch、finally、throw、throws
遇事不决,建议百度