JAVA基础语法
数据类型太基础了,直接讲常用的
顺序结构
由上到下顺序执行
public static void main(String[] args) {
System.out.println("1");
System.out.println("2");
System.out.println("3");
System.out.println("4");
}
选择结构
if
public static void main(String[] args) {
int i=5;
if (i==5){
System.out.println("i=5");
}
}
if-else
public static void main(String[] args) {
int i=6;
if (i==5){
System.out.println("i=5");
}else{
System.out.println("i不等于5或6");
}
}
多if
public static void main(String[] args) {
int i=5;
if (i==5){
System.out.println("i=5");
}else if (i==6){
System.out.println("i=6");
}else{
System.out.println("i不等于5或6");
}
}
嵌套if 伪代码
public static void main(String[] args) {
int i=5;
if (布尔表达式成立进入){
System.out.println("布尔表达式成立进入");
if (布尔表达式成立进入){
System.out.println("布尔表达式成立进入了第二层");
}
}
}
switch
public static void main(String[] args) {
int i=2;
switch(i){
case 1:
System.out.println("输入为1");
break;
case 2:
System.out.println("输入为2");
break;
case 3:
System.out.println("输入为3 ");
break;
}
}
JDK1.7之后支持使用字符串 本质上还是数字
public static void main(String[] args) {
String i="一";
switch(i){
case "一":
System.out.println("输入为1");
break;
case "二":
System.out.println("输入为2");
break;
case "三":
System.out.println("输入为3 ");
break;
}
}
循环结构
while
public static void main(String[] args) {
int i=0;
while (i<=10){
System.out.println(i);
i++;
}
}
1+2+…+100
public static void main(String[] args) {
int i=1;
int sum=0;
while (i<=100){
sum=sum+i;
i++;
}
System.out.println(sum);
}
do…while
先执行后判断
public static void main(String[] args) {
int i=1;
int sum=0;
do {
sum=sum+i;
i++;
}
while (i<=100);
System.out.println(sum);
}
for
public static void main(String[] args) {
int sum = 0;
for (int i=0;i<=100;i++){
sum=sum+i;
}
System.out.println(sum);
}
99乘法表
/**
① 先写出打印第一列 1*n=n
② 固定的1去掉,再用循环包起来。
③ 去掉重复项 i<=j
④ 调整改行处
*/
public static void main(String[] args) {
for (int j = 1;j<=9;j++){
for (int i = 1;i<=j;i++){
System.out.print(i+"*"+ j + "=" + j*i +"\t");
}
System.out.println();
}
}
增强for
public static void main(String[] args) {
int a[]={1,2,3,4,5,6,7,8,9};
//吧a数组赋值给x增强输出
for (int x:a){
System.out.println(x);
}
}
JAVA方法
public static void main(String[] args) {
new ceshi().add(1,5); //这个1 5是实际传入进去的实参
}
//add方法 void无返回值类型
public void add(int a,int b){ //ab是形参
System.out.println(a+b);
}
方法重载
同名方法但是参数列表(个数不同、类型不同、参数排列顺序不同)三种其中符合一种才是重载
public static void main(String[] args) {
new ceshi().add(1.6,5.7); //此处因为传值是double类型,所以走了同名的add方法中的double参数的方法
}
public void add(int a,int b){
System.out.println(a+b);
}
public void add(Double a,Double b){
System.out.println(a+b);
}
可变参数
JDK1.5开始的可变参数 一个方法中只能指定一个可变参数,并且是最后一个参数,普通参数需要在它之前声明
public static void main(String[] args) {
new ceshi().add(1,5);
}
public void add(int... a){
int num=0;
for (int x:a){
num=num+x;
}
System.out.println(num);
}
递归
计算阶乘
public static void main(String[] args) {
ceshi ceshi = new ceshi();
System.out.println(ceshi.f(5));
}
public int f(int n){
if (n==1){
return 1;
}else{
return n*f(n-1);
}
}
数组
//两种数组定义的方法
int[] a;
int b[];
public static void main(String[] args) {
//可以存放十个int数字 从零开始
int[] nums = new int[10];
nums[0]=0;
nums[1]=1;
nums[2]=2;
nums[3]=3;
nums[4]=4;
nums[5]=5;
nums[6]=6;
nums[7]=7;
nums[8]=8;
nums[9]=9;
//增强输出 也可以使用nums.length来获取数组长度
for (int x:nums){
System.out.println(x);
}
}
也可以直接使用int[] nums={1,2,3,4,5,6,7,8,9,10};静态初始化
数组倒置
public static void main(String[] args) {
//可以存放十个int数字 从零开始
int[] nums = new int[10];
nums[0]=0;
nums[1]=1;
nums[2]=2;
nums[3]=3;
nums[4]=4;
nums[5]=5;
nums[6]=6;
nums[7]=7;
nums[8]=8;
nums[9]=9;
//增强输出 也可以使用nums.length来获取数组长度
//创建了一个存放反数据的数组 长度和nums数组一样
int[] ints = new int[nums.length];
for (int i = 0,j = ints.length - 1; i<nums.length;i++,j--){
ints[j]=nums[i];
}
for (int anInt : ints) {
System.out.println(anInt);
}
}
二维数组
public static void main(String[] args) {
int [] [] array={{1,1},{2,1}};
for (int[] ints : array) {
for (int anInt : ints) {
System.out.print(anInt);
}
System.out.println();
}
}
冒泡排序算法
时间复杂度为o(n2)
public static void main(String[] args) {
int [] array={1,2,3,5,7,9,5,8,55};
int temp=0;
//数组长度-1次从头开始一遍
for (int i = 0; i < array.length-1; i++) {
//把相邻的两个数大小排序
//每一轮能把相邻的两个数大的排序到前面,数组长度-1次数就能排序完成
for (int j=0;j<array.length-1-i;j++){
if (array[j+1]>array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
for (int i : array) {
System.out.println(i);
}
}
通过添加标志位进行优化
public static void main(String[] args) {
int [] array={9,8,15,6,58,4,3};
int temp=0;
boolean flag = false;
//数组长度-1次从头开始一遍
for (int i = 0; i < array.length-1; i++) {
//把相邻的两个数大小排序
//每一轮能把相邻的两个数大的排序到前面,数组长度-1次数就能排序完成
flag=false; //减少更多无意义的排序
for (int j=0;j<array.length-1-i;j++){
if (array[j+1]>array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=true;
}
}
if (!flag){
//如果进来就是证明排序默认就是正常的,不需要做过多的排序浪费时间
break;
}
}
for (int i : array) {
System.out.println(i);
}
}
面向对象
新建学生类
//学生类
public class Student {
//说话方法
public void say(){
System.out.println("学生说话了");
}
}
在main中测试
new了一个Student对象,调用了他的say方法
public static void main(String[] args) {
Student student = new Student();
student.say();
}
如果Student的say方法使用static修饰后,是可以直接在main中使用Student.say()调用的。不需要实例化
static是和类一起加载的,不加static是在类实例化之后才存在的
构造器无参构造
new对象时候,被new对象会默认生成一个构造器(无参构造)
构造方法不许和类名相同且没有返回值也不能写void
public static void main(String[] args) {
Student student = new Student();
}
public class Student {
}
反编译class文件可以看到Student自带一个构造方法
public static void main(String[] args) {
new Student();
}
public class Student {
public Student() {
}
}
无参构造能做什么
可以实例化对象,赋初始值
使用无参构造对Student中的参数赋初始值
public class Student {
String StudentName;
public Student(){
StudentName="张三";
}
}
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.StudentName);
}
程序在new Student()时候会进入Student的无参构造对StudentName进行赋初始值,然后创建对象student
构造器有参构造
String StudentName;
public Student(){
}
//有参构造
public Student(String studentName){
StudentName=studentName;
}
一旦自定义了有参构造,还需要使用无参构造时候必须显式定义无参构造
封装
封装就是追求高内聚低耦合
封装通常需要禁止直接访问一个对象中国的数据来进行实际业务表示,需要通过接口来访问
高内聚:类的内部数据细节自己完成,不允许外部干涉
低耦合:只暴露少的方法给外部使用,尽可能解耦
在Student中定义属性
//姓名
private String Name;
//id
private int Id;
//性别
private char Sex;
因为以上属性使用private定义的,是私有的,不能在mian中直接new对象然后使用.直接调用
public static void main(String[] args) {
Student student1 = new Student();
//因为属性使用的private定义的(私有属性),不能直接使用.name获取
// student1.Name();会直接报错 'Name' 在 'Student' 中具有 private 访问权限
}
所以需要使用属性私有get/set
get/set就是可以提供一些公共public的一些get(获取)set(设置)方法
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
Student student1 = new Student();
//因为属性使用的private定义的(私有属性),不能直接使用.name获取
student1.setName("zhangsna");
System.out.println(student1.getName());
}
set中可以做点事情,比如性别字段可以去判断数据是否合法。设置输入性别如果不是女,自动为男
public void setSex(String sex) {
if (sex=="女"){
this.sex = sex;
}else{
this.sex = "男";
}
}
student1.setSex("难");
System.out.println(student1.getSex());
会自动吧输入错误的数据修改为默认值男
继承
Java中所有的类都默认继承Object类
java中只有单继承,没有多继承
新建person类,并使student类继承person类。子类是父类的扩展
//人类
public class person {
public void say(){
System.out.println("说了一句话");
}
}
//学生类
public class Student extends person{
}
public static void main(String[] args) {
Student student = new Student();
student.say();
}
这个时候就会输出person中say方法定义的说了一句话
super
person中定义属性name
protected String name="baicha";
student中定义同名属性
private String name="baicha1";
编写测试方法并且调用
public void test(){
System.out.println(name);
System.out.println(super.name);
}
public static void main(String[] args) {
Student student = new Student();
student.test();
}
经过测试会输出:
baicha1
baicha
由此可见super关键字可以调用到父类的属性参数
重写
新建两个类 A B ,A继承B。其中编写同名静态方法
public class A extends B{
public static void test(){
System.out.println("AAA");
}
}
public class B {
public static void test(){
System.out.println("BBB");
}
}
测试
public static void main(String[] args) {
A a = new A();
a.test();
B b = new A();
b.test();
}
输出结果为AAA BBB
多态
提供动态编译,增强可扩展性
创建两个类 student和person student继承person
new以下三个对象 父类的应用指向子类
student student1 = new student();
person student2 = new student();
Object student3 = new student();
对象能执行哪些方法主要看对象左边的类型
在student和person中创建同名方法test,输出一句话
public class person {
public void test(){
System.out.println("这是person的test");
}
}
public class student extends person{
public void test(){
System.out.println("这是student的test");
}
}
public static void main(String[] args) {
student student1 = new student();
person student2 = new student();
Object student3 = new student();
student1.test();
student2.test();
}
在子类重写父类方法时候,student1和2执行的是子类重写的方法,但是时候能执行此方法是看左边,比如student2主要看person类中是否有test方法,没有的话是不能执行的
输出结果为:
这是student的test
这是student的test
总结为一句话就是:能执行的(编译)看左边,运行看右边
编写子类独有方法test1
public void test1(){
System.out.println("这是student的test方法");
}
这时候使用student2去直接调用是无法调用的,需要对student2对象进行强制类型转换(由父类转子类、高转低)
((student)student2).test1();
向上转和向下转型
子类转父类,向上转,会丢失子类独有方法
父类转子类,向下转。需要强制转换
创建student和person student继承person
向上转型
//这就是向上转,子类转父类
person student2 = new student();
//student2.test1();丢失了test1,丢失之类独有方法
向下转型
student s = (student)student2; //student2指向的是父类型,强制转换(向下转型),使其包含了子类独有方法
s.test1();
抽象类
抽象类是不能new出来的
抽象类可以写普通方法,但是类中有抽象方法时必须为抽象类
编写抽象类
//类上添加abstract就是抽象类
public abstract class action {
//方法上添加abstract就是抽象方法,抽象方法只有约束,没有写方法实现
public abstract void test();
}
实现抽象方法,需要继承action
public class Demo extends action{
@Override
public void test() {
System.out.println("重写了action的test方法,这里是实现体");
}
}
为什么要有抽象类:因为java类只能单继承,但是接口可以多继承
接口
普通类:类中方法有具体实现
抽象类:抽象类有规范和实现,规范需要继承去编写规范的实现类
接口:只有规范
编写一个接口
public interface TestService {
// public abstract void test1();
void test1();
}
编写接口实现类
public class TestServiceImpl implements TestService{
@Override
public void test1() {
System.out.println("使用接口TestService编写的实现类TestServiceImpl的test1方法输出");
}
}
因为接口可以多继承,所以我们需要再写一个接口
public interface Test1Service {
void test2();
}
继承接口实现多继承
public class TestServiceImpl implements TestService,Test1Service{
@Override
public void test1() {
System.out.println("使用接口TestService编写的实现类TestServiceImpl的test1方法输出");
}
@Override
public void test2() {
System.out.println("使用接口TestService编写的实现类TestServiceImpl的test2方法输出");
}
}
内部类
内部类可以去操作私有属性和外部方法
编写内部类和普通类
public class inside {
public void out(){
System.out.println("这是inside类的外部方法");
}
public class inner{
public void in(){
System.out.println("这是内部类inner的in方法");
}
}
}
调用内部类和普通类,细节见注释
public static void main(String[] args) {
inside inside = new inside();
inside.out(); //可以使用new出来的对象直接调用外部方法
//用主类的对象去new内部类,就能去调用内部类对象了
inside.inner inner = inside.new inner();
inner.in();
}
异常
捕获异常
在main方法中执行一个必然出错的代码
System.out.println(1/0);
1/0是算术异常ArithmeticException
使用try catch去捕获处理异常
e.printStackTrace(); //打印错误信息
public static void main(String[] args) {
try { //这里面的程序运行出错就会捕获异常
System.out.println(1/0);
}catch (ArithmeticException e){//算术异常 其他的异常就用其他的异常去处理,或者使用Throwable去处理。Throwable是最高级异常,可以捕获error
System.out.println(e.toString());
System.out.println("出现了算数异常");
}//此处还可以跟更多catch,原理和ifelse类似,但是异常大小级别是从小打到,防止上面大的捕获到了就不会运行下面了
}
原来程序运行会输出Exception in thread “main” java.lang.ArithmeticException: / by zero
使用try捕获使用catch去接收算数异常后运行输出:
java.lang.ArithmeticException: / by zero
出现了算数异常
finally关键字
在上面捕获处理异常的基础上,finall关键字是不论什么情况都会执行的代码块,一般执行善后工作,比如关闭资源 finally是非必要的
public static void main(String[] args) {
try { //这里面的程序运行出错就会捕获异常
System.out.println(1/0);
}catch (ArithmeticException e){//算术异常
System.out.println(e.toString());
System.out.println("出现了算数异常");
}finally {
System.out.println("这是finally");
}
}
运行结果
java.lang.ArithmeticException: / by zero
出现了算数异常
这是finally
抛出异常
使用throw或者throws抛出异常
编写测试方法
public void test(int a,int b){
if (b==0){
throw new ArithmeticException(); //主动抛出算数异常
}
System.out.println(a/b);
}
测试
public static void main(String[] args) {
new ceshi().test(1,0);
}
这时候会主动判断,然后抛出算数异常(使用throw)
如果此处无法处理异常,需要抛出到更高的地方,就在方法上抛出异常(使用throws)
public static void main(String[] args) {
try {
new ceshi().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println("执行完test输出");
}
public void test(int a,int b) throws ArithmeticException{
System.out.println(a/b);
}
抛出异常后使用需要使用trycatch包裹,好处是如果出现异常了不影响下面的代码执行,因为此处的异常是算数异常,普通情况下会直接停住代码,现在这种情况可以继续执行下面的代码
运行结果:
java.lang.ArithmeticException: / by zero
at ceshi.test(ceshi.java:14)
at ceshi.main(ceshi.java:6)
执行完test输出
自定义异常
需要继承Exception类
编写我们自己的异常类
public class MyException extends Exception{
private int detail;
public MyException(int a){
this.detail = a;
}
@Override
//异常的打印信息
public String toString() {
return "MyException{" +
"detail=" + detail +"大于10"+
'}';
}
}
编写测试代码 其中是抛出异常,没有解决,调用时需要try catch
public void test(int a) throws MyException {
if (a>10){
throw new MyException(a);
}
}
测试
public static void main(String[] args) {
try {
new ceshi().test(11);
} catch (MyException e) {
e.printStackTrace();
}
}
运行结果:
MyException{detail=11大于10}
at ceshi.test(ceshi.java:14)
at ceshi.main(ceshi.java:6)