Java基础语法
1. Float定义变量:
Java数据类型long需要添加后缀L/l和float需要添加后缀F/f
float必须要加,不加默认是double。如14.23默认为double类型常量,而14.23f才为float常量。
2.因为float和double的精度不同,比较时同一数字会导致float比较大。
float变量在存储float类型的数据时保留8位有效数字。double变量在存储double类型的数据时保留8位有效数字。
float x = 0.4f;
double y = 0.4;
//x实际上储存的是0.4000000059604645 y则是0.4000000000000000
//所以x>y
3. Java标准输入的函数方法:
char c = (char)System.in.read()//1
Scanner t= new Scanner(System.in);char c=t.next();//2编译未通过
4.数组
//java允许int型变量的值指定数组的元素个数
int size = 30;
double num[] = new double[size];
//数组长度
float a[] = new float [12];
int b[][] = new int [3][6];
//a.length为12,b.length为3 二维数组名.length的值是它含有的一维数组的个数。
char a[] = {'C','h','i','n','a'};
System.out.println(a);
System.out.print("数组a 的引用:"+a);//字符型数组输出引用的办法
//输出:
China
数组a 的引用:[C@3d8c7aca
//数组默认值为0
int a[] = new int [3];
System.out.println(a[0]);
//输出
0
//通过^运算加密字符
char a1='十',a2='点',a3='进',a4='攻';
char secret='A';
a1=(char)(a1^secret);
a2=(char)(a2^secret);
a3=(char)(a3^secret);
a4=(char)(a4^secret);
System.out.println("密文:"+a1+a2+a3+a4);
a1=(char)(a1^secret);
a2=(char)(a2^secret);
a3=(char)(a3^secret);
a4=(char)(a4^secret);
System.out.println("原文:"+a1+a2+a3+a4);
//输出
密文:匀烸辚敺
原文:十点进攻
//二维数组列长度不同的赋值方法
int a[][] = new int [3][];
a[0] = new int [1];
a[1] = new int [2];
a[2] = new int [3];
//java独有的遍历数组的方法
int a[] = {1,2,3};
for(int i:a)
System.out.println(i);
//输出
1
2
3
//for-each遍历二维数组
int[][] a=new int[5][4];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = i*j;
}
}
for (int[] arr : a) {
for (int arr2 : arr) {
System.out.print(arr2+"\t");
}
System.out.println();
}
5.类
1.如果方法中的局部变量的名字与成员变量的名字相同,那么方法就隐藏了成员变量(暂时失效)。
2.成员变量有默认值,局部变量没有默认值。局部变量不赋值会编译错误。
3.类体的内容由两部分组成:成员变量的声明和方法的定义。
声明变量的时候可以赋初值,但是变量的赋值语句只能出现在方法体中。
class A{
int a = 12;//声明的时候可以赋初值
}
class A{
int a;
a = 12;//错误,不能出现赋值语句
}
class A{
int a;
void hhh{
a = 12;
}//这样改
}
让java立刻进行“垃圾收集”的操作,可以让System类调用gc()方法。
可变参数
//声明
static int getSum(int...x)//注意:这样第一个和最后一个参数要注意
{
int sum = 0;//x[0]、x[1]、...x[n-1]代表了传递过来的参数
for(int i:x)
{
sum+=i;
}
return sum;
}
关联关系:
依赖关系:
实例变量和类变量(static变量、静态变量)实例方法和类方法
实例变量和类变量(static变量、静态变量)
类变量:new 出来的不同的对象时,分配给这些对象的类变量的占有相同的内存。
实例变量: new的时候分配不同的存储空间。
class Dog
{
float x;//实例变量
static int y;//类变量
}
实例方法和类方法
1.当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,
只有该类创建对象后,类中的实例方法才会分配入口地址。
2.当类的字节码文件被加载到内存时,类的类方法就分配了入口地址,从而
类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名直接调用。
实例方法不仅可以操控实例变量,也可以操作类变量。
类方法不可以操作实例变量(类创建对象之前,实例变量还没有分配内存)
static方法 不用创建对象就可以用类名直接调用它
class A
{
public static void main(String args[])
{
A a1 = new A();
a1.hh();
}
void hh()
{
System.out.print("haha!");
}
}
class A
{
public static void main(String args[])
{
hh();//直接调用
A.hh();
}
static void hh()
{
System.out.print("haha!");
}
}
java类的单继承性,一个子类只能继承一个父类
上转型对象
//1
Animal a;
a = new Tiger();
//2
Animal a;
Tiger b = new Tiger();
a = b;
-
对象b的上转型a的实体是有子类B创建的,但是上转型对象会失去子类B的一些属性和功能。上转型对象具有以下特点:
- 上转型对象不能操作子类新增加的成员变量,不能使用子类新增的方法。即为较子类B失去一些属性和功能,这些属性和功能是新增的。
- 上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法。即为上转型对象可以操纵父类原有的属性和功能,无论这些方法是否被重写。
- 上转型对象调用方法时,就是调用子类继承和重写过的方法。而不会是新增的方法,也不是父类原有的方法。
- 可以将对象的上转型对象再强制转换到一个子类对象,强制转换过的对象具有子类所有属性和功能。
6.this关键字
this可以出现在实例方法和构造方法中,但是不能出现在类方法中。
public class People{
int leg,hand;
String name;
People(String s){
name=s;
this.init(); //可以省略this,即将this.init();写成init();
}
void init(){
leg=2;
hand=2;
System.out.println(name+"有"+hand+"只手"+leg+"条腿");
}
public static void main(String args[]){
People boshi=new People("布什"); //创建boshi时,构造方法中的this就是对象boshi
}
}
当实例成员变量的名字和局部变量的名字相同时,成员变量前面
的 **this.** 或者是 **类名.** 就不可以省略。 方法同理。
public class StudyTest
{
int a = 3;//实例变量
static int b = 4;//类变量
void ha(int a)
{
System.out.println("局部变量a的值为:"+a);
System.out.println("实例成员变量this.a的值为:"+this.a);
System.out.println("类成员变量this.a的值为:"+StudyTest.b);
}
public static void main(String args[])
{
StudyTest a = new StudyTest();
a.ha(5);
}
}
Java中如果没有import语句引入包中的类,那么也可以直接带着包名使用该类。
java.util.Date date = new java.util.Date();
7.访问权限
-
类中的实例方法总是可以操作该类中的实例变量和类变量;类方法总是可以操作该类的中的类方法。(不能操作类中的实例方法原因前面)
-
public类和友好类
class前加上public关键字就是public类
class前面没有关键字的就是友好类
!!!如果源文件使用import语句引入了另一个包的类,并用该类创建了一个对象,那么该类的这个对象将不能访问自己的友好变量和友好方法。也就是说子类和父类不在一个包的时候,父类中的private和友好访问权限的成员变量不会被继承。
其他点基本和c++无差别
权限高低排序:public > protected > 友好的 > private
public class A{...}//这个就是public类
class A{...}//这个就是友好类
**在创建对象的时候**
PUBLIC类可以不受限制地用和访问
友好类最大用和访问范围是同一个包
插播一个关于main函数的小知识点
因为main()方法是由Java虚拟机调用的,所以必须是public,虚拟机调用的main()方法的时候,
不需要产生任何对象,所以main()方法声明为static,且不需要返回值,所以必须声明为void。
protected的进一步说明
一个类A中的protected成员变量和方法可以被它的子孙类继承,例如B是A的子类,C是B的子类,D是C的子类,那么B、C、D类都继承了A类的protected成员变量和方法。在没有讲述子类之前,我们曾对访问修饰符proteced进行了讲解,现在需要对protected总结得更全面些。如果用D类在D本身中创建了一个对象,那么该对象总是可以通过“.”运算符访问继承的或自己定义的protected变量和protected方法的,但是,如果在另一个类中,例如在Other类中用D类创建了一个对象object,该对象通过“.”运算符访问protected变量和protected方法的权限如下所示。
(1) 对于子类D自己声明的protected成员变量和方法,只要Other类和D类在同一个包中,object对象
就可以访问这些protected成员变量和方法。
(2) 对于子类D从父类继承的protected成员变量或方法,需要追溯到这protected
成员变量或方法所在的“祖先”类,例如可能是A类,只要Other类和A类在同一个包中,
object对象能访问继承的protected变量和protected方法。
- 子类方法的重写注意事项
– 重写父类的时候,不允许降低方法的访问权限,但可以提高访问权限。
8.super关键字
-
定义:java中的super关键字是一个引用变量,用于引用直接父类对象。
每当创建子类的实例时,父类的实例被隐式创建,由super关键字引用变量引用。 -
子类隐藏继承的成员变量 ->>> 重写父类中的变量或方法
为什么要用 super 关键字
- 由于子类不能继承父类的构造方法,要调用父类的构造方法或者是要调用被子类隐藏的成员,必须在子类的构造方法体的第一行使用 super() 方法。该方法会调用父类相应的构造方法来完成子类对象的初始化工作。
用处
- 调用父类的构造方法
- 访问父类中实例变量
- 访问父类的方法
super() 必须是在子类构造方法的第一行。
如果没有构造函数,编译器会自动提供默认构造函数。
1.用super操作被隐藏的成员变量和方法
class Sum {
int n;
float f() {
float sum=0;
for(int i=1;i<=n;i++)
sum=sum+i;
return sum;
}
}
class Average extends Sum {
int n;
float f() {
float c;
super.n=n;
c=super.f();
return c/n;
}
float g() {
float c;
c=super.f();
return c/2;
}
}
public class Example5_7 {
public static void main(String args[]) {
Average aver=new Average();
aver.n=100;
float resultTwo=aver.g(); float resultOne=aver.f();
System.out.println("resultOne="+resultOne);
System.out.println("resultTwo="+resultTwo);
}
}
2.用super调用父类的构造方法
class Student {
int number;String name;
Student() {
}
Student(int number,String name) {
this.number=number;
this.name=name;
System.out.println("我的名字是:"+name+ "学号是:"+number);
}
}
class UniverStudent extends Student {
boolean 婚否;
UniverStudent(int number,String name,boolean b) {
super(number,name);
婚否=b;
System.out.println("婚否="+婚否);
}
}
public class Example5_8 {
public static void main(String args[]) {
UniverStudent zhang=new UniverStudent(9901,"何晓林",false);
}
}
9.final关键字
- final类不允许被继承,没有子类
- final方法修饰父类中的一个方法,这个方法将不允许被子类重写。
- final常量:如果成员变量或者是局部变量被修饰位final,那么他就是常量。
10.abstract
- abstract 类 里面可以含有非抽象方法
如果将一个类设置为abstract,则此类必须被继承使用。此类不可生成对象,必须被继承使用。 Abstract可以将子类的共性最大限度的抽取出来,放在父类中,以提高程序的简洁性。 Abstract虽然不能生成对象,但是可以声明,作为编译时类型,但不能作为运行时类型。 Final和abstract永远不会同时出现。
非抽象类中不可以含有抽象方法 - abstract 方法 只允许声明不允许实现
当abstract用于修饰方法时,此时该方法为抽象方法,此时方法不需要实现,实现留给子类覆盖,子类覆盖该方法之后方法才能够生效。
11.接口与实现
- 接口的定义
interface Printable
{
final int MAX = 100;
void add();
fload sum(float x, float y);
}
- 接口体
- 接口体中只有抽象方法
- 并且
- 所有的常量的访问权限一定都是public,而且是static变量(允许省略public、final、static修饰符)
- 所有的抽象方法的访问权限一定都是public(允许省略public abstract修饰符)
interface Printable
{
public static final int MAX = 100;//等价于 int MAX = 100;
public abstract void add();//等价于 void add();
}
- 实现接口
- 一个非抽象类实现了某个接口,那么这个类必须重写这个接口中的所有方法。类在重写方法的时候要去掉abstract修饰符、给出方法体,同时方法的访问权限一定要明显地用public来修饰(访问权限在重写之后不能降低)
public interface Computable
{
int MAX = 46;
int f(int x);
}
public class China implements Computable //China类实现Computable接口
{
int number;
public int f(int x) //不要忘记public关键字
{
int sum=0;
for(int i=1;i<=x;i++)
{
sum=sum+i;
}
return sum;
}
}
public class Japan implements Computable //Japan类实现Computable接口
{
int number;
public int f(int x)
{
return MAX+x; //直接使用接口中的常量
}
}
public class Example6_1
{
public static void main(String args[])
{
China zhang;
Japan henlu;
zhang=new China();
henlu=new Japan();
zhang.number=32+Computable.MAX; //用接口名去访问接口的常量
henlu.number=14+Computable.MAX;
System.out.println("zhang的学号"+zhang.number+",zhang求和结果"+zhang.f(100));
System.out.println("henlu的学号"+henlu.number+",henlu求和结果"+henlu.f(100));
}
}
- 抽象类实现一个接口,不用重写接口中的所有方法。
interface Computable
{
final int MAX = 100;
void speak(String s);
int f(int x);
}
abstract class A implements Computable
{
public int f(int x)
{
int sum = 0;
for(int i = 1;i <= x;i ++) sum+=i;
}
return sum;
}
- 接口的细节
- 程序可以用接口名访问接口中的变量,但是如果一个类实现了接口,那么该类可以直接在类体中使用该接口中的变量。
- public接口和友好接口 和类几乎一样
- 父类实现了接口,子类也会继承这个实现了的接口
- 接口也可以被继承
- 接口回调
Com com;//Com是一个接口,com是接口声明的一个变量
ImpleCom object = new ImpleCom();//ImpleCom 是实现了Com接口的类
com = object;//接口回调
interface ShowMessage {
void 显示商标(String s);
}
class TV implements ShowMessage {
public void 显示商标(String s) {
System.out.println(s);
}
}
class PC implements ShowMessage {
public void 显示商标(String s) {
System.out.println(s);
}
}
public class Example6_2 {
public static void main(String args[]) {
ShowMessage sm; //声明接口变量
sm=new TV(); //接口变量中存放对象的引用
sm.显示商标("长城牌电视机"); //接口回调。
sm=new PC(); //接口变量中存放对象的引用
sm.显示商标("联想奔月5008PC机"); //接口回调
}
}
- 接口的多态
- 有接口产生的多态是指在不同的类在实现同一个接口时具有不同的实现方式,那么接口变量在回调接口方法时就可能具有多种形态。
- 接口参数
- 方法的参数是接口类型,那么接口参数就可以回调类实现的接口方法。
interface SpeakHello {
void speakHello();
}
class Chinese implements SpeakHello {
public void speakHello() {
System.out.println("中国人习惯问候语:你好,吃饭了吗? ");
}
}
class English implements SpeakHello {
public void speakHello() {
System.out.println("英国人习惯问候语:你好,天气不错 ");
}
}
class KindHello {
public void lookHello(SpeakHello hello) { //接口类型参数
hello.speakHello(); //接口回调
}
}
public class Example6_5 {
public static void main(String args[]) {
KindHello kindHello=new KindHello();
kindHello.lookHello(new Chinese());
kindHello.lookHello(new English());
}
}
12.内部类和异常类
内部类
- 内部类的外嵌类的成员变量和方法在内部类中依然有效
- 内部类的类体中不能声明类方法和类变量(即前面不能有static)
- 非内部类不能是static类。内部类加上static就是外嵌类中的一种静态数据类型,程序就可以在其他类中使用static内部类来创建对象了。 和之前一样static内部类不能操作外嵌类中的实例变量。
匿名类
- 匿名类是内部类
- 匿名类可以继承父类的方法也可以重写父类的方法
- 匿名类不能声明静态成员和方法
- 和接口有关的匿名类也相似
public class TestAnonymousInterClass {
public static void main(String args[]) {
TestAnonymousInterClass test = new TestAnonymousInterClass();
test.show();
}
// 在这个方法中构造了一个匿名内部类
private void show() {
Out anonyInter = new Out() {// 获取匿名内部类实例
@Override
void show() {// 重写父类的方法
System.out.println("this is Anonymous InterClass showing.");
}
};
anonyInter.show();// 调用其方法
Out out = new Out();
out.show();// 调用其方法
}
}
// 这是一个已经存在的类,匿名内部类通过重写其方法,将会获得另外的实现
class Out {
void show() {
System.out.println("this is Out showing.");
}
}
异常类
- 抛出异常、捕获异常
public class Example7_4
{
public static void main(String args[ ])
{
int n = 0,m = 0,t = 1000;
try
{
m = Integer.parseInt("8888");
n = Integer.parseInt("ab89"); //发生异常,转向catch
t = 7777; //t没有机会被赋值
}
catch(NumberFormatException e)
{
System.out.println("发生异常:"+e.getMessage());
}
System.out.println("n="+n+",m="+m+",t="+t);
try
{
System.out.println("故意抛出I/O异常!");
throw new java.io.IOException("我是故意的");
//System.out.println("这个输出语句肯定没有机会执行,所以必须注释掉,否则编译出错");
}
catch(java.io.IOException e)
{
System.out.println("发生异常:"+e.getMessage());
}
}
}
- 自定义异常类
public class BankException extends Exception {
String message;
public BankException(int m,int n) {
message="入账资金"+m+"是负数或支出"+n+"是正数,不符合系统要求.";
}
public String warnMess() {
return message;
}
}
public class Bank {
private int money;
public void income(int in,int out) throws BankException {
if(in<=0||out>=0||in+out<=0) {
throw new BankException(in,out); //方法抛出异常,导致方法结束
}
int netIncome=in+out;
System.out.printf("本次计算出的纯收入是:%d元\n",netIncome);
money=money+netIncome;
}
public int getMoney() {
return money;
}
}
public class Example7_5 {
public static void main(String args[]) {
Bank bank=new Bank();
try{ bank.income(200,-100);
bank.income(300,-100);
bank.income(400,-100);
System.out.printf("银行目前有%d元\n",bank.getMoney());
bank.income(200, 100);
bank.income(99999,-100);
}
catch(BankException e) {
System.out.println("计算收益的过程出现如下问题:");
System.out.println(e.warnMess());
}
System.out.printf("银行目前有%d元\n",bank.getMoney());
}
}
- try-catch-finally
- try-catch语句中执行了return语句,finally的语句仍然会被执行
- try-catch执行System.exit(0),那么不会执行finally的语句
-
throw 和 throws 的区别
-
Throw: 作用在方法内,表示抛出具体异常,由方法体内的语句处理。
具体向外抛出的动作,所以它抛出的是一个异常实体类。若执行了Throw一定是抛出了某种异常。 -
Throws:作用在方法的声明上,表示如果抛出异常,则由该方法的调用者来进行异常处理。
主要的声明这个方法会抛出会抛出某种类型的异常,让它的使用者知道捕获异常的类型。
出现异常是一种可能性,但不一定会发生异常。 -
throws E1,E2,E3只是告诉程序这个方法可能会抛出这些异常,方法的调用者可能要处理这些异常,而这些异常E1,E2,E3可能是该函数体产生的。
-
throw则是明确了这个地方要抛出这个异常。
-
代码块中可能会产生3个异常,(Exception1,Exception2,Exception3)。
如果产生Exception1异常,则捕获之后再抛出,由该方法的调用者去处理。
如果产生Exception2异常,则该方法自己处理了(即System.out.println(“出错了!”);)。所以该方法就不会再向外抛出Exception2异常了,void doA() throws Exception1,Exception3 里面的Exception2也就不用写了。
而Exception3异常是该方法的某段逻辑出错,程序员自己做了处理,在该段逻辑错误的情况下抛出异常Exception3,则该方法的调用者也要处理此异常。