Java基础

Java基础

参考毕向东Java基础教程

1.自动类型转换(隐式类型转换)

  • 两种类型是相互兼容的

  • 目的数据类型的占用范围要一定要大于源类型

正向过程:由低字节向高字节自动转换,byte->short->int->long->float->double

2.强制类型转换(显式类型转换)

格式:目标类型 变量 = (目标类型)源类型变量/常量
逆向过程:使用强制转换,可能丢失精度。

3.数据类型自动提升

多种不同数据类型的表达式中,类型会自动向范围表示大的值的数据类型提升。
没有final修饰的变量相加后会被自动提升为int型。

4.程序流程控制

判断结构:
  • if else与三元运算符的区别:三元运算符由于是运算符,因此必须有结果。
  • Java语言中语句结束一般有两种方式:以分号 ; 或后大括号 } 结束,以 } 结束的一般为流程控制语句。
    局部代码块
{
   int m = 89;
   System.out.println("Hello World!..."+m);
}
System.out.println("Over..."+m);        //编译报错

局部代码块一执行完, m变量在内存中就会被释放。因此局部代码块可以定义局部变量的生命周期。为了节约内存空间,在确保后面不会在使用此变量的情况下,可以使用局部代码块的形式,执行完后,其空间就会被腾出来(虚拟机在内存当中开辟的空间是有限的,除非在启动虚拟机的时候设置需要的空间)。

选择结构
1.switch能判断的数据类型:
  • 基本数据类型:byte, short, char, int
  • 包装数据类型:Byte, Short, Character, Integer
  • 枚举类型:Enum(Jdk 5+ 开始支持)
  • 字符串类型:String(Jdk 7+ 开始支持)
2.
  • 程序一执行到switch,会把大括号内所有的语句加载到内存中。
  • switch中条件放置无顺序,但执行有顺序。
    Example1:即使default放在第一位,也会先判断case
switch(表达式)
{
    default:
        执行语句;
        break;
  case 取值1:
        执行语句;
        break;
    case 取值2:
        执行语句;
        break; 
    ...
}
  • 程序遇到满足条件的值后,如果没有break,则会继续向下执行,之后的case不再进行判断直接执行里面的语句,直到遇到break或执行到大括号终结。
    Example2
int x = 2;
swtich(x)
{
    default:
      System.out.println("d");
      //break;
    case 4:
      System.out.println("a");
      //break; 
    case 1:
      System.out.println("b");
      break;
    case 3:
      System.out.println("c");
      break;
}
//输出结果为d, a, b
  • Example3:多个值,对应相同执行语句
int month = 3;
switch(month)
{
    case 3:
    case 4:
        System.out.println(month+"月对应的是春季");
        break;
}

执行到case 3,满足条件,但没有执行语句break继续往下执行并且不判断,执行完case 4中的语句再break。

ifswitch的应用

  • 对于几个固定的值判断,建议使用switch语句,因为其会将具体的答案都加载进内存,效率相对高一点。
  • 常用的为if,不建议用switch语句,因为其功能性较差,且书写麻烦。
循环结构
  • whilefor可以互换,区别在于for为了循环而定义的变量for循环结束就在内存中释放,而while循环使用的变量在循环结束后还可以继续使用。
5.函数
1、特点
  • 函数只有被调用才会被执行
  • 函数中只能调用函数,不可以在函数内部定义函数。

Example

class Demo 
{
    public static void main(String[] args) 
    {
        System.out.println(add(3,5));
    }
    public static void add(int a, int b)
    {
        System.out.println(a + b);
        return;
    }
}

编译出错: System.out.println(add(3,5));此处不允许使用void类型。

2、函数的重载(overload)

概念:在同一类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。
特点:与返回值类型无关,只看参数列表。
好处:方便于阅读,优化了程序设计。

Example 1

public static int add(int a, int b)
{
    return a+b;
}
public static double add(int a, int b)
{
    return a+b;
}

编译报错:已在XX中定义add(int, int)…,Java是严谨性语言,如果函数出现调用的不确定性,会编译失败。

Example 2: 打印乘法表

/**
打印指定参数的任意乘法表
*/
public static void printCFB(int num)
{
    for(int x=1; x<=num; x++)
    {
        for(int y=1; y<=x; y++)
        {
            System.our.print(y+"*"+x+"="+y*x+"t");
        }
        System.out.println();
    }
}
/**
打印标准乘法表(不指定参数的情况下)
*/
public static void printCFB()
{
    for(int x=1; x<=9; x++)
    {
        for(int y=1; y<=x; y++)
        {
            System.our.print(y+"*"+x+"="+y*x+"t");
        }
        System.out.println();
    }
}

如上,一般只要一重载,代码就会重复;可以通过调用的方式,减少重复代码。


/**
打印指定参数的任意乘法表
*/
public static void printCFB(int num)
{
    for(int x=1; x<=num; x++)
    {
        for(int y=1; y<=x; y++)
        {
            System.our.print(y+"*"+x+"="+y*x+"t");
        }
        System.out.println();
    }
}
/**
打印标准乘法表。
*/
public static void printCFB()
{
    printCFB(9);
}

一般由于参数个数的原因重载,都能复用;而如果是参数类型,则不行。

6.数组

1、格式
/*=======第一种格式=======*/
元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
/*=========示例========*/
int[] arr = new int[5];

/*=======第二种格式=======*/
元素类型[] 数组名 = new 元素类型[]{元素1, 元素2, ...};
/*=========示例========*/
int[] arr = new int[]{3,5,1,7};   //用new,常规初始化方式
int[] arr = {3,5,1,7};            //静态初始化方式
//以上两种方式在大部分情况下都是通用的,但它们在重新赋值或传参时会有一点小差别

Example

int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
//均输出0(默认赋值为0)
2、数组的内存分配及特点
Java内存分为五片
  • 寄存器(CPU使用)
  • 本地方法区(调用系统底层内容)
  • 方法区(别名【数据区、共享区、share data】,存储方法)
  • 栈内存(基本数据类型):存储的都是局部变量,变量所属的作用域一旦结束,该变量就会自动释放。
  • 堆内存(引用数据类 ):存储数组和对象(其实数组也是对象),凡是new建立的对象都在堆中。
堆的特点:
  • 每一个实体都有首地址值。
  • 堆内存中的每一个变量都有默认初始化值,根据类型的不同而不一样,整数:0,小数:0.0或者0.0f,boolean:false,char :‘u0000’,实体:null。
  • 垃圾回收机制:当堆中的实体没有被任何变量指向时,不像栈一样,会立刻被释放,而是会被视作垃圾,被自动回收,垃圾回收机制会不定时的,自动检测堆里的垃圾,进行回收。C++需要程序员手动回收堆里的垃圾,析构函数。

Example

int[] arr = new int[3];
//arr在栈中,new int[3]在堆中,堆中存的是实体,实体的用途:用于封装数据,存储很多数据
数组操作常见问题

Example 1: ArrayIndexOutOfBoundsException异常

int[] arr = new int[3];
System.out.println(arr[3]);

编译完,不会出错,因为编译时不会在内存中建立数组,因此也不会找角标。
运行时,产生问题,当访问到数组中不存在的角标/索引时,就会产生ArrayIndexOutOfBoundsException异常。

Example 2: NullPointerException异常

int[] arr = new int[3];
arr = null;
System.out.println(arr[0]);

运行出错,当引用型变量没有任何实体指向时,还在用其操作实体,就会产生NullPointerException异常。

数组常见操作

Example 1: 获取最值

class Demo
{
    public static void main(String[] args)
    {
        int[] arr = {-34,-19,-11,-109,-3,-56};
        int max = getMax(arr);
        System.out.println("max="+max);
    }
    public static int getMax(int[] arr)
    {
        int max = arr[0];
        for(int x=1; x<arr.length; x++)
        {
            if(arr[x]>max) max = arr[x];
        }
        return max;
    }
}

注意max初始化的问题,若初始化为0,则 判断不出 最大值。

注意:
1、给定一个有序数组,若往该数组中存储一个元素,并保证数组仍然是有序的,那么这个元素存储的角标如何获取–>return min。
2、

int[] arr = {13,15,19,27,33,45,78,106};
Arrays.binarySearch(arr,45);
//若元素存在,返回元素所在的位置;
//若元素不存在,返回的是-插入点-1;之所以-1,是因为避免返回0,例如Arrays.binarySearch(arr,5)

Example 2: 进制转换
可以通过Integer类的方法直接将十进制数转换为对应的进制数:

System.out.println(Integer.toBinaryString(-6));
System.out.println(Integer.toHexString(5));
System.out.println(Integer.toOctalString(32));

7.二维数组

格式1:int[][] arr = new int[3][2];
  • 定义了名称为arr的二维数组
  • 二维数组中有3个一维数组
  • 每一个一维数组中有2个元素
  • 一维数组的名称为arr[0]arr[1]arr[2]
  • 给第一个一维数组1角标位赋值为78写法:arr[0][1] = 78;
格式2:int[][] arr = new int[3][];
  • 二维数组中有3个一维数组
  • 每个一维数组都是默认初始化值null
  • 可以对这三个一维数组分别进行初始化
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];
格式3:
int[][] arr = {{3,1,7},{5,8,2,9},{4,6}};
int[][] arr = new int[3][2];
int[] arr[] = new int[3][2];
int arr[][] = new int[3][2];

Example1:直接打印二维数组

int[][] arr1 = new int[3][2];
System.out.println(arr);       //[[I@c17164
System.out.println(arr[0]);    //[I@1fb8ee3
System.out.println(arr[0][0]); //0

int[][] arr2 = new int[3][];
System.out.println(arr);       //[[I@c17164
System.out.println(arr[0]);    //null
System.out.println(arr[0][0]); //NullPointerException

Example2:数组长度

System.out.println(arr.length);    //打印二维数组的长度-->就是一维数组的个数。
System.out.println(arr[1].length); //打印二维数组中角标为1的一维数组的长度。

8.继承

概述
  • 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承单独的类即可。
  • 多个类可以称为子类,单独的类称为父类或者超类。
  • 通过extends关键字让类与类之间产生继承关系。
class SubDemo extends Demo{}
  • 继承的好处:
    继承的出现提高了代码的复用性
    继承的出现让类与类之间产生了关系,提供了多态的前提。
特点
  • Java中支持单继承,不支持多继承
    一个子类只能有一个直接父类,否则若多个父类中有相同成员,会产生调用的不确定性
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...{} //error
  • Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{} 

当要使用一个继承体系时:

  1. 查看该体系中的顶层类,了解该体系的基本功能
  2. 创建体系中的最子类对象,完成功能的使用
  • 什么时候定义继承?
    当类与类之间存在着所属(“is a”)关系的时候,就定义继承。如xxx是yyy的一种,则xxx extends yyy。或者判断父类中的功能是否子类都应该具备,若有些不具备,则不存在继承。不要仅为了获取其他类中某个功能而去继承 。
super关键字

this和super的用法很相似。
注意:两者都要求在构造方法的首行,所以两者不能同时使用

1、this
  • this三大作用:调用属性,调用方法,利用this表示当前对象
  • this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。

this的用法在java中大体可以分为3种:

  1. 普通的直接引用: this相当于是指向当前对象本身。
  2. 形参与成员名字重名,用this来区分:
class  Person {
     private int age =  10;
     public Person(){
     	System.out.println( "初始化年龄:" +age);
	 }
     public int GetAge(int age){
         this.age = age;
         return this.age;
     }
}
 
public class test1 {
     public static void main(String[] args) {
         Person Harry =  new  Person();
         System.out.println( "Harry's age is " + Harry.GetAge( 12 ));
     }
}       

运行结果:

初始化年龄:10
Harry's age is 12
  1. 引用构造函数
    这个和super放在一起讲,见下面。
2、super

super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
super也有三种用法:

  1. 普通的直接引用
    与this类似,super相当于是指向当前对象的父类,这样就可以用super.xxx来引用父类的成员。
  2. 子类中的成员变量或方法与父类中的成员变量或方法同名
class Country {
     String name;
     void value() {
        name = "China";
     }
}
  
class City extends Country {
     String name;
     void value() {
	     name = "Shanghai";
	     super.value();       //调用父类的方法
	     System.out.println(name);
	     System.out.println(super.name);
     }
  
     public static void main(String[] args) {
	        City c= new City();
	        c.value();
     }
}

运行结果:

Shanghai
China

可以看到,这里既调用了父类的方法,也调用了父类的变量。若不调用父类方法value(),只调用父类变量name的话,则父类name值为默认值null
3.引用构造函数
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

class  Person { 
     public  static  void  prt(String s) { 
        System.out.println(s); 
     } 
   
     Person() { 
        prt( "父类·无参数构造方法: " + "A Person." ); 
     } //构造方法(1) 
    
     Person(String name) { 
        prt( "父类·含一个参数的构造方法: " + "A person's name is "  + name); 
     } //构造方法(2) 
} 
    
public  class  Chinese  extends  Person { 
     Chinese() { 
        super ();  // 调用父类构造方法(1) 
        prt( "子类·调用父类”无参数构造方法“: " + "A chinese coder." ); 
     } 
    
     Chinese(String name) { 
        super (name); // 调用父类具有相同形参的构造方法(2) 
        prt( "子类·调用父类”含一个参数的构造方法“: " + "his name is "  + name); 
     } 
    
     Chinese(String name,  int  age) { 
        this (name); // 调用具有相同形参的构造方法(3) 
        prt( "子类:调用子类具有相同形参的构造方法:his age is "  + age); 
     } 
    
     public  static  void  main(String[] args) { 
        Chinese cn =  new  Chinese(); 
        cn =  new  Chinese( "codersai" ); 
        cn =  new  Chinese( "codersai" ,  18 ); 
     } 
}

运行结果:

父类·无参数构造方法: A Person.
子类·调用父类”无参数构造方法“: A chinese coder.
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
子类:调用子类具有相同形参的构造方法:his age is 18

注意: 父类中的私有内容,子类是否具备——实际上子类对于父类中私有的成员变量是继承了的,即定义子类对象时,在堆中存有父类的私有成员变量,只是不能直接访问,所以确切地说,应该是子类中不能直接地访问父类中的私有内容。

函数覆盖(Override)

当对一个类进行子类的扩展时,子类需要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就使用覆盖操作完成。

注意:

  • 父类中的私有方法不可以被覆盖。
  • 在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。
  • 覆盖时,子类方法权限一定要大于等于父类方法权限。
  • 静态只能覆盖静态,或被静态覆盖(非静态不能覆盖静态,静态不能覆盖非静态,否则会报编译错)。
子类的实例化过程

构造函数不会继承更不会覆盖

子类中所有的构造函数都会默认访问父类中的空参数的构造函数。

public class Father 
{
    public Father()
    {
        System.out.println("Father run");
    }
}
class Son extends Father
{
    public Son()
    {
        //super(); //默认会调用父类的空参构造函数
        System.out.println("Son run");
    }
}
  • 当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数。
  • 子类构造函数中至少有一个访问父类构造函数。

注意,类默认的空参构造函数的修饰符与类保持一致。

class Demo
{
    /*
    Demo()
    {
        super(); //父类为Object
        return;
    }
    */
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值