java学习笔记
java数据类型的转换
Java中可以进行不同数据类型的加减乘除运算吗?是可以的。在算术运算符中已经体验过如果两个整数(int)相除会去掉小数部分。如果需要保留小数部分,可以让除数或者被除数变为double类型的(5变为5.0)。其实Java是自动的将int的那个数变为了double类型了也就是Java自动的将整数变为了浮点数。例如5/2.0 其实是5.0/2.0
1、 自动类型转换(也叫隐式类型转换)
可以将一个数赋值给更大数值范围的变量,例如可以经byte 变量赋值给short变量可以将short变量赋值给int变量可以将int变量赋值给long变量。
Java内部其实做了工作就是自动将数值进行了类型提升,就叫做自动类型转换(也叫隐式类型转换)
byte b = 1; //00000001 short s = b; //00000000 00000001 int i = s; long lon = i; double d = lon; //1.0 |
自动类型转换(也叫隐式类型转换)
要实现自动类型的转换,需要满足两个条件,第一两种类型彼此兼容,第二目标类型取
值范围必须大于源类型。所有的数字类型,包括整形和浮点型彼此都可以进行转换。
例如:
byte b=100; int x=b; System.out.println(x);//程序把b结果自动转换为int类型。 |
2、 强制类型转换(也叫显式类型转换)
不可以将一个数值赋给范围更小数值范围的变量,除非进行类型转换。
byte b = 100; b = b + 2; System.out.println(b); |
上述例子发生了什么,发生了类型转换。
b+2 遇到了加法运算,2默认是int类型,byte类型b变量存储的值自动类型提升为
了int类型。执行完加法运算后的结果就是int类型,想要将int的类型值放入到byte类型变量b中,无法放入,编译报错。
byte b=1; b=(byte)(b+2); |
当两种类型彼此不兼容,或者目标类型取值范围小于源类型(目标是byte源是int)
无法自动转换,此时就需要进行强制类型转换。
1、 什么时候要用强制类型转换
比如小数部分只想保留整数部分.
一定要清楚要转换的数据在转换后数据的范围内否则会损失精度.
public static void main(String[] args) { byte b = 100; b = (byte) (b + 2); System.out.println(b); // 102 //舍弃小数部分 double d=5.5; int num=(int)d; } |
2、 表达式的数据类型自动提升
算术表达式,逻辑表达式
所有的byte型、short型和char的值将被提升到int型。
如果一个操作数是long型,计算结果就是long型;
如果一个操作数是float型,计算结果就是float型;
如果一个操作数是double型,计算结果就是double型。
分析 System.out.println(‘a’+1)结果?
自动类型提升
byte b = 3; int x = 4; x = x + b;// b会自动提升为int 类型参与运算。 System.out.println(x);// 7
|
强制类型转换
byte b = 2; /* * 强制类型转换,强制将b+2强制转换为byte类型,再赋值给b */ b = (byte) (b + 2); System.out.println(b);// 4 |
思考1
byte b=126;
问:既然数据默认的有数据类型,那么126 默认是int类型的,为什么存储到byte类型时不会报错呢。
126 是常量java在编译时期会检查该常量(每个常量)是否超出byte类型的范围。如果没有可以赋值。
思考2:byte b=128;能否正常的编译和运行。
该语句会出现编译错误,128超出了byte变量的存储范围,所以出现编译错误。
文档注释用/** */表示,是java特有的注释,其中注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。
java中byte变量的范围是 -128~127
Math.random()的简单使用
Math.random()可以使系统默认随机选取大于等于0.0且小于1.0的伪随机Double值,是java语言常用的代码
int i=(int)(Math.random()*21);
Scanner的基本使用
Scanner 被称为输入流扫描器类,从控制台读取数据的 String nextLine() 从控制台返回一行,忽略空格。
int: nextInt() 从控制台返回一个 int 型数据,如果时间格式不对将抛出。java.util.InputMismatchException。 long: nextLong() 从控制台返回一个 long 型数据,如果时间格式不对将抛出java.util.InputMismatchException。 float: nextFloat() 从控制台返回一个 float 型数据,如果时间格式不对将抛出java.util.InputMismatchException。 double: nextDouble() 从控制台返回一个 double 型数据,如果时间格式不对将抛出java.util.InputMismatchException。 boolean: hasNext() 判断输入流还有没有下一个数据 ,
首先要好导入包:import java.util.Scanner;或者java.util.*
java.util是一个包名,java.util.*代表该包内的所有类
例子:
1 import java.util.Scanner; 2 public class TextScanner{ 3 public static void main(String [] args){ 4 //创建Scanner对象 接受从控制台输入 5 Scanner input = new Scanner(System.in); 6 System.out.println("请输入名字:"); 7 //接受String型 8 String name = input.next();//注意不是nextString() 9 System.out.println("请输入学号"); 10 //接受int型 11 int id = input.nextInt();//什么类型next后面就接什么 注意大小写 12 //输出结果 13 System.out.println("名字为:"+name+"\t学号为:"+id); 14 } 15 }
CompareToIgnoreCase的使用
提示: musics[i].compareToIgnoreCase(music) > 0
上面这个方法是比较字符串的方法,
前面的值减 去后面的值,比如 :"aa".compareToIgnoreCase("cc")的值是-2 如果前面的值大返回正数,如果后面的大于前面的,返回负数,或者等于前面的,返回0
例如 “Haha".compareToIgnoreCase("Aha") 是比较 haha 字符串 和 aha字符串 (此方法自动忽略大小写)
h 比 a 大, 所以返回 是 7(相减得来的), (根据字母表顺序)
Java中的构造方法:
就和OC里面的自定义初始化方法一样,为了在创建对象的时候就给对象属性赋初始值,并且只走一次,因为第二次的话又是另一个对象了
使用构造器时需要记住:
1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名)
2.每个类可以有一个以上的构造器
3.构造器可以有0个、1个或1个以上的参数
4.构造器没有返回值,前面不能有 void
5.构造器总是伴随着new操作一起调用,注意:不是手动调用的,而是java虚拟机自动调用的
举例:
1 public class A{ 2 public A(){ 3 System.out.println("调用了无参的构造函数"); 4 } 5 public A(String mess){ 6 System.out.println("调用了有参的构造函数\n"+ 7 "参数内容为:"+mess); 8 } 9 } 10 public class Test{ 11 public static void main(String [] args){ 12 A a_1=new A();//调用无参的构造函数 13 A a_2=new A("Hello");//调用有参的构造函数 14 } 15 }
效果图:
在继承中使用构造方法:
默认情况下是自动调用父类的无参构造方法,如果使用super调用父类构造器的语句必须是子类构造器的第一条语句,不信的话,你可以试试,果断的报以下的错误:
如果子类构造器没有显式地调用父类的构造器,则将自动调用父类的默认(没有参数)的构造器。如果父类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用父类的构造器,则java编译器将报告错误
text.java文件代码:
1 class A{ 2 public A(){ 3 System.out.println("调用了A的无参构造函数"); 4 } 5 public A(String mess){ 6 System.out.println("调用了A的有参的构造函数\n"+ 7 "参数内容为:"+mess); 8 } 9 } 10 class B extends A{ 11 public B(){ 12 System.out.println("调用了B的无参构造函数"); 13 } 14 public B(String mess){ 15 super(mess); //如果没有这句就会默认调用父类的无参构造方法 16 System.out.println("调用了B的有参构造函数\n"+ 17 "参数内容为:"+mess); 18 } 19 } 20 public class text{ 21 public static void main(String [] args){ 22 B b_01=new B(); 23 B b_02=new B("你好"); 24 } 25 }
效果图上:
如果把15行的代码删了,就会这样:
toString方法的作用:
Object类提供的toString()方法总是返回该对象实现类的”类名+@+hashCode”值,这个返回值不能真正实现“自我描述”功能如图:
当Java对象和字符串进行连接运算时,系统自动调用Java对象toString()方法返回值和字符串进行连接运算下面代码效果相同
String pStr=p+”字符串”;
StringpStr=p.toString()+”字符串”;
test.java里面的代码:
1 public class test { 2 3 public static class User{ 4 String name; 5 int age; 6 public User(String name,int age){ 7 this.name = name; 8 this.age = age; 9 } 10 @Override 11 public String toString() { 12 return "my name is "+name+",i'm "+age+" years old"; 13 } 14 15 } 16 public static void main(String[] args) { 17 System.out.println(new User("Jack",16)); 18 } 19 }
效果图上:
其中,@Override的作用:
系统可以帮你检查方法的正确性,@Overridepublic String toString(){...}这是正确的一旦写错 写成这样@Overridepublic String tostring(){...}编译器可以检测出这种写法是错误的 这样能保证你的确重写的方确而如果不加@Overridepublic String tostring(){...}这样编译器是不会报错的 它只会认为这是你自己新加的一个方法仅此而已,说白了,就是试图覆盖父类方法而确又写错了方法名时才发挥威力的。
Java中的静态的理解与main函数为什么是静态的?(static)
首先理解什么是static,java中的static有什么作用?
在C语言中的static表示只初始化一次,而在这java中也一样,不过还多了一些功能,被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。要这个类被加载,Java虚拟机(JVM)就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为:
类名.静态方法名(参数列表...)
类名.静态变量名
静态方法可以直接通过类名调用,任何的实例也都可以调用,
因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
理解了这些后,我们就可以上代码
1 public class text { 2 3 public void main(String[] args) { 4 System.out.println("dfdfd"); 5 } 6 }
编绎通过了,但运行就报错了,如图:
原因是:
非静态成员函数在执行前必须先构造并实例化该函数所在的类,也就是说必须先创建 一个对象。
如果允许非静态的main,那么main函数所在的类必须先进行实例化,那么就需要再写个函数去实例化main所在的类,再调用main,这个实例化代码又写在哪呢?如果它也是非静态的,那就又要写这个实例化代码,那还有完没完啊??!!因此,没有为什么!JAVA语言就规定了main必须是静态的。
我们由浅入深,首先看代码:
1 public class text { 2 class People 3 { 4 int id; 5 String name; 6 int age; 7 public People(String name,int age){ 8 this.name=name; 9 this.age=age; 10 System.out.println(this.name+this.age); 11 } 12 } 13 public static void main(String[] args) { 14 System.out.println(new People("Jack",16)); 15 } 16 }
编绎就报错了,如图:
原因是:
this 是指向当前对象的引用,需要对象实例化以后才能赋值。而静态成员都是类所属的,不需要对实例化就可以使用,所以在静态上下文中引用this(可以理解为空指针)时可能其还未赋值,所以应不能这样使用。this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this。说白了,就是不能用类来调用
分析:People成了text的非静态内部类,属于text的一个成员,在静态方法main中不能访问非静态的成员,也就是说不能直接new Clerk()只能通过外部类的对象访问(创建一个对象)。
所以我们可以这样:
1 public class text { 2 class People 3 { 4 int id; 5 String name; 6 int age; 7 public People(String name,int age){ 8 this.name=name; 9 this.age=age; 10 System.out.println(this.name+this.age); 11 } 12 } 13 public static void main(String[] args) { 14 System.out.println(new text().new People("Jack",16)); 15 } 16 }
编绎运行通过 :
Java中有明文规定,类变量不能直接访问实例变量,实例变量可以(但不推荐)能访问类变量,所以说一个static修饰的变量在调用普通方法;或一个static修饰的方法在调用普通变量,这是不允许的。
两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
总结:
静态的可以访问静态的,静态的不能访问非静态的,非静态的可以访问静态的(因为静态的我个人理解是在JVM编绎时就存在了,与虚拟机共存死亡,而非静态的还不一定存在,所以理解很简单)
如果是在构造方法的前面加上修饰符static ,就会报错,如图:
原因是:
java中构造方法可以有任何访问的修饰符,public、private、protected或者没有修饰符 ,都可以对构造方法进行修饰。不同于实例方法的是构造方法不能有任何非访问性质的修饰符修饰,例如static、final、synchronized、abstract等都不能修饰构造方法。
解释:构造方法用于初始化一个实例对象,所以static修饰是没有任何意义的;多个线程不会同时创建内存地址相同的同一个对象,所以synchronized修饰没有意义;
构造方法不能被子类继承,所以final和abstract修饰没有意义。
2、返回类型是非常重要的,实例方法可以返回任何类型的值或者是无返回值(void),而构造方法是没有返回类型的,void是空类型,所以void也不行。
3、至于命名就是构造方法与类名相同,当然了实例方法也可以与类名相同,但是习惯上我们为实例方法命名的时候通常是小写的,另一方面也是与构造方法区分开。
而构造方法与类名相同,所以首字母一般大写。
注意:构造方法中可以调用普通(实例)方法和构造方法的
直接上代码:调用普通方法
1 public class text { 2 class People 3 { 4 int id; 5 String name; 6 int age; 7 public People(String name,int age){ 8 this.name=name; 9 this.age=age; 10 System.out.println(this.name+this.age); 11 fun2(); 12 } 13 14 public void fun2(){ 15 System.out.println("ceshi2"); 16 } 17 } 18 public static void main(String[] args) { 19 System.out.println(new text().new People("Jack",16)); 20 } 21 }
效果图上:
构造方法中调用构造方法:
1 public class text { 2 class People 3 { 4 int id; 5 String name; 6 int age; 7 public People(String name,int age){ 8 this.name=name; 9 this.age=age; 10 System.out.println(this.name+this.age); 11 this(); 12 this(20); 13 } 14 public People(){ 15 System.out.println("调用默认的构造方法"); 16 } 17 public People(int age){ 18 19 System.out.println("调用有参数的构造方法,参数是:"+age); 20 } 21 22 } 23 public static void main(String[] args) { 24 System.out.println(new text().new People("Jack",16)); 25 } 26 }
编绎就报错了:
因此得改成这样的:
1 public class text { 2 class People 3 { 4 int id; 5 String name; 6 int age; 7 public People(String name,int age){ 8 this(); 9 //this(20); //一个构造方法里面只能调用一个构造方法,加上这个就会报错了 10 this.name=name; 11 this.age=age; 12 System.out.println(this.name+this.age); 13 } 14 public People(){ 15 this(20); 16 System.out.println("调用默认的构造方法"); 17 } 18 public People(int age){ 19 20 System.out.println("调用有参数的构造方法,参数是:"+age); 21 } 22 23 } 24 public static void main(String[] args) { 25 System.out.println(new text().new People("Jack",16)); 26 } 27 }
效果图:
结论:在构造方法中可以调用普通方法(对象方法),也可以在构造方法中调用构造方法,格式是:this(参数名,没有的话就不填),并且必须是第一条语句 且只能有一条。
构造代码块的使用与理解:
普通代码块:是最常见的代码块,在方法里用一对“{}”括起来的数据,就是普通的代码块,
构造代码块:是在类中直接定义的,用“{}”括起来的代码。每次调用构造方法前执行,都会先执行构造代码块。
静态代码块:他在类中的成员位置,用“{}”括起来的代码。只不过他用了static修饰了,,且执行一次
代码块测试题:结合了,普通代码块,构造代码块,静态代码块,是大家能够够清楚的明白代码块执行的数序以及规律
他会先执行class 文件class Nihaoa到内存。所以他会执行class Nihaoa类下的静态块,在执行main方法,编译class GouZao类,然后执行代码,静态的执行一次,构造方法块每次执行
静态内部粝与非静态内部类的使用与理解
什么是内部类?就是在类中再定义类的类就叫做内部类。
首先先看静态内部类,代码:
1 public class text { 2 int a=0; 3 static int b=0; 4 public static class People 5 { 6 int id; 7 String name; 8 int age; 9 public People(String name,int age){ 10 this.name=name; 11 this.age=age; 12 fun1(); 13 //fun2(); 14 //System.out.println("name is:"+name+" age is:"+a); 15 System.out.println("name is:"+name+" age is:"+b); 16 } 17 } 18 public static void fun1(){ 19 System.out.println("调用静态的方法"); 20 } 21 public void fun2(){ 22 System.out.println("调用非静态的方法"); 23 } 24 public static void main(String[] args) { 25 System.out.println(new People("Jack",16)); 26 } 27 }
运行通过,效果:
如果把注释部分去掉后,就会报错,如图:
因此,得出:静态内部类的非静态成员(比如this)可以访问外部类的静态变量/静态方法,而不可访问外部类的非静态变量/非静态方法;
再来看非静态内部类:
1 public class text { 2 public class People 3 { 4 int id; 5 String name; 6 int static age; 7 public People(String name,int age){ 8 this.name=name; 9 this.age=age; 10 System.out.println("name is:"+name+" age is:"+age); 11 } 12 } 13 public static void main(String[] args) { 14 System.out.println(new People("Jack",16)); 15 } 16 }
运行效果图:
得出:非静态内部类则不能有静态成员。为什么?
假设要访问非静态内部类里的静态成员,由于是非静态内部类,那么必须先声明外部类的实例(也就是对象)才行,内部类也会被初始化,这时就变成对象调用,这就不符合静态的作用了(因为没意义)
其实总结就一句话,静态的可以访问任何静态的,因为在JVM时就分配了内存(个人理解),不能访问非静态的,非静态的可以访问任何静态的,非静态的要访问非静态的,要实例化对象才行。
单例设计模式:
所谓的单例设计模式:顾名思义就是全局就一个对象(一个地址)
1 /* 2 单例设计模式 : 一个类只能够创建一个对象出来 3 软件行业中设计模式23中 4 可能在java学习中会讲到如下设计模式: 5 1.单例设计模式 6 2.观察者设计模式 7 3.模块设计模式(mvc) 8 4.装饰设计模式 9 5.工厂模式 10 11 设计模式 : 用来解决同一类问题的解决方案(固定的步骤) 12 13 单例的设置步骤: 14 1.创建一个对象把他设置为私有的静态成员变量,保证对象唯一 15 2.把构造方法设置为私有的,防止new一个对象。 16 3.定义一个公开的静态方法,返回值为上面的对象。 17 18 19 */ 20 21 /* 22 oc中单例: 23 +(SingleDog *)default{ 24 25 //保证对象唯一 26 static SingleDog s; 27 if(s == null){ 28 s = [[SingleDo alloc] init]; 29 } 30 return s; 31 } 32 33 34 35 36 37 */ 38 39 40 //如何实现单例设计模式 41 //--------饿汉单例设计模式 42 class SingleDog{ 43 44 String name; 45 int age; 46 //保证对象唯一 47 // 声明本类的引用变量, 并且把对象创建出来 48 private static SingleDog s = new SingleDog(); // 静态的成员变量 49 //私有化构造方法 ,防止通过new来创建对象 50 private SingleDog(){} 51 //提供一个静态方法来接收唯一的对象 52 public static SingleDog getInstance (){ 53 54 return s; 55 } 56 57 } 58 59 //------------懒汉单例设计模式-------------- 60 //不安全 ,推荐使用上面的写法。 61 class SingleDog2 { 62 63 //声明本类的引用变量,不创建 64 private static SingleDog2 s; 65 66 //私有化一个构造方法 67 private SingleDog2() {}; 68 69 //提供一个静态的方法来接收唯一的对象 70 public static SingleDog2 getInstance(){ 71 72 if(s==null){ 73 74 s = new SingleDog2(); 75 } 76 77 return s; 78 79 } 80 } 81 82 class Demo7 { 83 public static void main(String[] args){ 84 85 SingleDog sd1 = SingleDog.getInstance(); 86 sd1.name = "老王"; 87 SingleDog sd2 = SingleDog.getInstance(); 88 SingleDog sd3 = SingleDog.getInstance(); 89 90 System.out.println(sd1); 91 System.out.println(sd2); 92 System.out.println(sd3); 93 } 94 }
在50行和67行用到了private,表示是私有的,外部的类不能访问,如果访问就报错,即对内可见,对外不见,所以我们常常把单例对象封装在一个类中,比如主函数在该类中,那么private就没有意义了,因为有没有都一样的。如:
1 public class a{ 2 static class People{ 3 private static People p = new People(); 4 //重写默认的构造方法 5 private People(){ 6 System.out.println("dfdfdfdfdf"); 7 }; 8 public static People getInstance(){ 9 return p; 10 } 11 } 12 public static void main(String[] args){ 13 People sss = new People(); //这一句没有报错,因此private就没有意义了 14 People s=People.getInstance(); 15 People ss=People.getInstance(); 16 System.out.println(s); 17 System.out.println(ss); 18 } 19 }
效果图:
abstract(抽象类)的使用(与interface的区别):
所谓的抽象类就好比一道 抽象的数学题,你一步步做出来了就觉得很简单了,而在java中抽象类是abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例(因为方法有可能是抽象方法,没有实现,那就没意义了),可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法,不然就会报错,并且抽象方法必须在抽象类中。
标准概念:
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
代码:
1 public class a{ 2 abstract static class People{ 3 } 4 public static void main(String[] args){ 5 People p = new People(); 6 } 7 }
运行结果:
抽象方法是没有方法体的(也就是没有大括号,只有声明,没有实现,类似于OC中的protocol),留给子类去实现。
1 public class a{ 2 abstract static class People{ 3 //abstract void fun(); //这是对的 4 abstract void fun(){} //不能方法体,这样写是错误的 5 } 6 public static void main(String[] args){ 7 } 8 }
编译:
一个抽象类中是可以有非抽象的方法,并且也可以不出现抽象方法的,如:
1 public class a{ 2 abstract static class People{ 3 //String name; 4 //abstract void fun(); //这是对的 5 // abstract void fun(){} //不能方法体,这样写是错误的 6 void fun1(){ 7 System.out.println("haha"); //抽象类中是可以定义非抽象方法的 8 } 9 } 10 class Student extends People 11 { 12 public Student(){ 13 fun1(); 14 } 15 } 16 public static void main(String[] args){ 17 Student s = new a().new Student(); 18 } 19 }
运行:
一个抽象类中是可以存在构造方法。作用是让子类能过初始化父类中的变量。如:
1 public class a{ 2 abstract static class People{ 3 String name; 4 //abstract void fun(); //这是对的 5 // abstract void fun(){} //不能方法体,这样写是错误的 6 void fun1(){ 7 System.out.println("name is :"+ name); //抽象类中是可以定义非抽象方法的 8 9 } 10 public People(){ //抽象类的构造方法的作用是用于初始化成员变量 11 name = "yuan"; 12 } 13 } 14 class Student extends People 15 { 16 public Student(){ 17 fun1(); 18 } 19 } 20 public static void main(String[] args){ 21 Student s = new a().new Student(); 22 } 23 }
运行:
总结:
1,abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法。
2,abstract修饰方法,会使这个方法变成抽象方法,声明(定义)而没有实现,实现部分以";"代替。需要子类继承实现(覆盖)。
3.abstract修饰符在修饰类时必须放在类名前。
4.abstract修饰方法就是要求其子类覆盖(实现)这个方法。调用时可以以多态方式调用子类覆盖(实现)后的方法,也就是说抽象方法必须在其子类中实现,除非子类本身也是抽象类。
5.父类是抽象类,有抽象方法,子类继承父类,并把父类中的所有抽象方法都实现(覆盖),抽象类中有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。
abstract能修饰成员变量吗??
答:不能。原因:只有public, protected, private, static, final, transient 和 volatile 能修饰成员变量。
abstract关键字的使用场景:
我们在描述一个事物的时候,发现这个事物确实存在某种行为,但是这种行为又不具体,那么这个时候就可以抽取这种行为 声明一个没有实现的行为,这种行为就叫抽象的行为,那么这个时候就需要用到抽象类。
使用abstract时需要注意:
1、不能和private一起使用。原因:abstract声明的方法必须要被重写,如果设为private就互相矛盾了
2、不能和static使用。原因:因为static 方法是类方法,必须要有方法体(也就是实现),就像main函数,有且仅有一个,它是不允许子类覆写,而且而abstract方法是没有实现的方法,是必须由子类来覆写的,两者完全矛盾,你说呢?
3、不能和final一起使用。原因:final修饰过的是不能修改的,而且必须要初始化,而abstract必须得重写才行,矛盾了。