逢考必过,祝复习考试的你,顺利通过,B站账号@狼群里的小杨,记得点赞收藏加关注,一键三连哦!
第一章
知识点总结
1、java语言的主要贡献者是James Gosling
2、开发Java应用程序的基本步骤是:编写源文件、编译源文件、运行程序
3、如果源文件中有多个类,那么至多有一个类可以是public类
4、源文件中有多个类时,这些类可以都不是public类,即java源文件中可以没有public类。
5、Java源文件可以没有主类。
6、java应用程序必须有主类
7、必须用文本编辑器编写源文件
8、java编译器位于java安装目录的\bin文件夹中,名字是javac.exe
第二章
知识点总结
1、汉字可以出现在标识符中
2、未加任何修饰符的小数、加了后缀d的小数、科学计数形式都是double,如3.14、3.14d、2e5、
3.14E2
3、int [] a; int a[];都是声明了一个一维数组
4、float foo = 0x0123; 是正确的float变量声明。
5、char ch =‘\u0061’;是正确的char变量声明。\u表示Unicode编码,扩展自ASCII编码。
6、char型字符在Unicode表中的位置范围是0至65535.
第三章
1、关系运算符和逻辑运算符的运算结果都是boolean型数据。
第四章
1、构造方法没有类型
2、类中的实例变量在用该类创建对象的时候才会被分配内存空间。
3、构造方法也可以重载
4、类中的类方法(static方法)只能操作类变量(static变量),不可以操作实例变量。
5、this不可以出现在类方法中,类方法可直接通过类调用 ,this必须与具体对象关联。
6、this关键字代表某个对象,不能出现在类方法中(static方法)
this调用对象的构造方法举例
注意Cat类中的Cat()构造方法
原题见实验6-2(动物世界)
abstract class Animal {
protected int legs;
abstract void eat();
protected Animal(int legs){
this.legs = legs;
}//of Animal
void walk(){
if (legs>4)
System.out.println(legs+"条腿"+"爬行");
else
System.out.println(legs+"条腿"+"跑");
}
}
class spider extends Animal{
protected spider() {
super(8);
}
@Override
void eat() {
System.out.println("蜘蛛用网捕食猎物");
}
}
interface Pet {
void setName(String name);
String getName();
void play();
}
class Cat extends Animal implements Pet{
String name;
Cat(String name) {
super(4);
this.name = name;
}// of Cat
Cat(){
this("");
}
@Override
void eat() {
System.out.println("猫吃鱼");
}
@Override
public void setName(String name) {
this.name = name;
}//of setName
@Override
public String getName() {
return name;
}// of getName
@Override
public void play() {
System.out.println("小猫陪主人玩耍");
}// of play
}//of Cat
class Fish extends Animal implements Pet{
private String name;
protected Fish() {
super(0);
}
@Override
void eat() {
System.out.println("主人喂食鱼食");
}
@Override
void walk() {
System.out.println("鱼没有腿,不能行走,只能游!");
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void play() {
System.out.println("供人们观赏享乐!");
}
}
public class Try{
public static void main(String[] args) {
Animal one = new spider();//实现蜘蛛对象
one.eat();
one.walk();
System.out.println("");
Cat two = new Cat();//实现猫对象
two.setName("豆丁");
System.out.println("猫的名字:"+two.getName());
two.eat();
two.play();
two.walk();
System.out.println("");
Fish three = new Fish();
three.setName("大鲨鱼");
System.out.println("鱼的名字:"+three.getName());
three.eat();
three.play();
three.walk();
}
}
7、如果源文件有package语句,该语句必须是源文件的第一条语句。
8、一个java文件中,在不同类中是可以有多个public static void main(String [] args)
示例如下:
package demo;
public class cs {
cs(){
System.out.println("你好啊! world!");
}
public static void main(String[] args) {
new cs();
}
}
class a{
public static void main(String[] args){
}
}
一个java程序一般只需要一个入口,即只需要一个类包含main方法,而其他类都是被用于main方法直接调用或间接调用。
main方法不是一定要放在public 修饰的类中
示例:
package demo;
class Dog{
Dog(){
System.out.println("I'm a dog.");
}
public static void main(String[] args){
new Dog();
new Cat();
}
}
class Cat{
Cat(){
System.out.println("I'm a cat.");
}
}
文件中没有一个public类,程序也能正常运行。
9、类的名字和文件名一致,并且包含main函数的类,叫做主类,一个java源文件可以没有主类。
10、一个java源文件默认有“import java.lang.*”语句。
11、方法的参数名字不可以和方法中声明的局部变量的名字相同。
12、类的名字在习惯上准守驼峰规则。
13、习惯将方法名及变量名的首字母小写。
14、不可以用protected、private修饰类(不包括内部类 inner class)
15、用public或不加任何修饰,来修饰类,即只有public类和友好类
16、Float是java.lang包中一个类的名字,而float是java关键字,用来声明float基本类型变量
17、组合关系也叫has a,属于弱耦合关系。
18、编译器不提示程序使用了空对象(让一个空对象去调用实例方法),但程序运行超时会出现NullPointerException异常。
19、不可以用static修饰构造方法。
注意:static和对象没有关系,但是构造方法是用于创建对象的,相互矛盾;同时static修饰的方法可以直接通过类名.静态方法名(实参);调用,但是构造方法不允许手动调用。
20、类中的类变量(static)在该类被加载到内存时(即使该类为创建对象)就会被分配内存空间。
21、构造方法的访问权限可以是public,protected,private或友好的。
22、方法中声明的局部变量不可以用public,protected,private,static修饰
第五章
1、除了java.lang.Object类,任何一个类有且仅有一个父类。
2、一个非final类可以有多个子类
3、java.lang包中Object类是所有其他类的祖先类。
4、如果子类和父类不在同一个包中,子类不继承父类的protected成员。
5、子类不继承父类的构造方法
6、不可以用final修饰构造方法
注意:final方法是约束子类不能覆盖,但是构造方法本身不允许子类继承。谈不上覆盖。(构造方法不是通过覆盖得到的,所以没必要用final修饰)
7、如果在子类的构造方法中,没有显示地写出super关键字来调用父类的某个构造方法,那么编译器默认地有:
super();
调用父类的无参构造方法(如果父类没有这样的构造方法,代码将出现编译错误)
注意:super关键字形成的语句必须是子类构造方法中的第一条语句。
8、final类不能被继承,即不能有子类。
9、abstract类中可以没有abstract方法
10、多态性就是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为(多:子类数目,态:父类某个方法)
11、不允许同时用static和abstract修饰同一方法。
12、不允许同时用final和abstract修饰同一个方法或类。
13、如果子类可以继承父类的某个方法,那么子类就有权利重写这个方法。
14、如果一个类的所用构造方法的访问权限都是private的,那么意味着这个类不能有子类
原因:一个类的private方法不能在其他类中被使用,但子类的构造方法中一定会调用父类的某个构造方法。
15、可以用public,protected,private修饰构造方法。
16、子类在方法重写时,不可以把父类的类(static)方法重写为实例方法,也不能把父类的实例方法重写为类(static)方法。
17、子类重写父类的方法时,不允许降低方法的访问权限,但可以提高访问权限
访问限制修饰符按访问权限从高到低排列:public,protected,友好的,private
18、如果子类是abstract类,允许子类将父类的非abstract方法重写为abstract方法,也可以不重写(直接继承)。
19、如果一个非抽象类是某个抽象类的子类,那么它必须重写父类的抽象方法,即给出方法体(将abstract方法重写为非abstract方法)
20、子类对象的上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法(失掉了一些行为)。
注意:如果上转型对象想要使用子类新增的成员变量或是方法,则必须进行类型转换,将上转型对象强制转换成子类对象。
例如:
//父类PackageCharge
public class PackageCharge {
String name;
double baseMonthCharge = 8;
public String getName(){
return name;
}
void setName(String name){
this.name = name;
}
public double getBaseMonthCharge() {
return baseMonthCharge;
}
}
public interface ChargeOfMessage {
void setMessagePrice(double Message);//设置每条短信价格
double getMessagePrice();//获取每条短信价格
void setMessageMonthCharge(double MessageCharge);//设置短信费用月租
double getMessageMonthCharge();//获取短信费月租
}
public interface ChargeOfData {
void setDataPrice(double Data);//设置每Gb流量价格
double getDataPrice();//获取每Gb流量价格
void setDataMonthCharge(double MonthData);//设置流量费月租
double getDataMonthCharge();//获取流量费月租
}
public interface ChargeOfCalling {
void setCalling(double Calling);//设置每分钟通话价格
double getCallingPrice();//获取每分钟通话价格
void setCallingMonthCharge(double MonthCalling);//设置通话费月租
double getCallingMonthCharge();//获取通话费月租
}
//子类SuperPackage,子类继承的三个接口实现的接口中的方法都属于子类新增的方法,父类PackageCharge的对象无法调用。
public class SuperPackage extends PackageCharge implements ChargeOfCalling,ChargeOfMessage,ChargeOfData {
private double CallingPrice;
@Override
public void setCalling(double CallingPrice) {
this.CallingPrice = CallingPrice;
}
@Override
public double getCallingPrice() {
return CallingPrice;
}
private double MonthCalling;
@Override
public void setCallingMonthCharge(double MonthCalling) {
this.MonthCalling = MonthCalling;
}
@Override
public double getCallingMonthCharge() {
return MonthCalling;
}
private double DataPrice;
@Override
public void setDataPrice(double DataPrice) {
this.DataPrice = DataPrice;
}
@Override
public double getDataPrice() {
return DataPrice;
}
private double MonthDataPrice;
@Override
public void setDataMonthCharge(double MonthDataPrice) {
this.MonthDataPrice = MonthDataPrice;
}
@Override
public double getDataMonthCharge() {
return MonthDataPrice;
}
private double MessagePrice;
private double MessageMonthCharge;
@Override
public void setMessagePrice(double MessagePrice) {
this.MessagePrice = MessagePrice;
}
@Override
public double getMessagePrice() {
return MessagePrice;
}
@Override
public void setMessageMonthCharge(double MessageCharge) {
this.MessageMonthCharge = MessageCharge;
}
@Override
public double getMessageMonthCharge() {
return MessageMonthCharge;
}
}
import java.io.BufferedWriter;
import java.io.*;
import java.security.MessageDigest;
import java.text.DecimalFormat;
//主类
public class phone {
public static void main(String[] args) {
PackageCharge superPackage;
double totalMonthCharge;
superPackage = new SuperPackage();//父类对象存储了子类对象的引用变成了上转型
SuperPackage tmp = (SuperPackage) superPackage; //通过强制类型转换以后父类对象变成子类对象以后才可以调用新增的方法和成员变量。
tmp.setName("超级套餐");
tmp.setDataPrice(1);
tmp.setDataMonthCharge(20);
tmp.setCalling(0.15);
tmp.setCallingMonthCharge(15);
tmp.setMessagePrice(0.09);
tmp.setMessageMonthCharge(5);
totalMonthCharge = tmp.getCallingMonthCharge()+tmp.getDataMonthCharge()+tmp.getMessageMonthCharge()+tmp.getBaseMonthCharge();
String result = "";
DecimalFormat doubleFormat = new DecimalFormat("#####.##");
SuperPackage sp = (SuperPackage)superPackage;
result += String.format("套餐名: %s\r\n", sp.getName());
result += String.format("流量费: %s(元/Gb) / %s(元/月)\r\n", doubleFormat.format(sp.getDataPrice()), doubleFormat.format(sp.getDataMonthCharge()));
result += String.format("通话费: %s(元/分) / %s(元/月)\r\n", doubleFormat.format(sp.getCallingPrice()), doubleFormat.format(sp.getCallingMonthCharge()));
result += String.format("短信费: %s(元/条) / %s(元/月)\r\n", doubleFormat.format(sp.getMessagePrice()), doubleFormat.format(sp.getMessageMonthCharge()));
result += String.format("总月租: %s(元/月)\r\n", totalMonthCharge);
System.out.print(result);
result += digest(result, "") + "此行勿删!";
writeTxt(result);
}
public static void writeTxt(String result){
try{
BufferedWriter fout = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("out.dat")));
fout.write(result);
fout.flush();
fout.close();
}catch (IOException e) {
e.printStackTrace();
}
}
public static String digest(String dataStr, String slat) {
String result = "";
try {
dataStr = dataStr + slat;
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(dataStr.getBytes("UTF8"));
byte s[] = m.digest();
for (int i = 0; i < s.length; i++) {
result += Integer.toHexString((0x000000FF & s[i]) | 0xFFFFFF00).substring(6);
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
return result;
}
}
}
21、如果成员变量被修饰为final的,就是常量,用户在声明时必须指定该常量的值。
22、static方法也可以同时是final方法
23、abstract和final不能同时修饰类或方法
24、static和abstract不能同时修饰一个方法。
25、如果一个类中有abstract方法,这个类必须是abstract类。
第六章
1、一个源文件中既可以定义接口,也可以定义类。
2、接口中只有常量,没有变量。
3、接口中可只有abstract方法,不能有非abstract方法。
4、接口中可以有abstract方法或default修饰的带方法体的方法(例如注解)。
5、接口中的定义变量默认是常量,必须有初始值。
6、可以用接口名直接访问接口中的常量
7、不能用final修饰接口
8、接口中的访问权限一定是public,定义接口时可以省略public。
9、抽象类既可以重写接口中的方法也可以直接拥有接口中的方法。
10、接口也是java中一个重要数据类型,用接口声明的变量称作接口变量。
11、接口变量中可以存放实现接口的类的实例的引用。
12、把实现某一接口的类创建的对象的引用赋值给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法。
第七章
1、java支持在一个类中定义一个类,这样的类称作该类的内部类。
2、内部类的外嵌类的成员变量在内部类中仍然有效。
3、内部类中的方法也可以调用外嵌类中的方法。
4、内部类的类体中不可以申明类变量和类方法。
- 注意:非静态内部类不能有静态成员!
成员内部类必须先实例化外部类对象然后再实例化成员内部类;
非static的内部类,在外部类加载的时候,并不会加载它,所以它里面不能有静态变量或者静态方法。
5、外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员。
6、可以用protected、private修饰内部类。
7、内部类仅供它的外嵌类使用,其他类不可以用某个类的内部类声明对象。
8、static内部类不能操作外嵌类的实例成员变量。
9、非匿名内部类也可以实现接口。
10、非匿名内部类也可以有(内部)子类。
11、内部类可以是final类。
12、不可能用匿名类声明一个对象,但可以用匿名类创建一个对象。
13、匿名子类(和子类有关的匿名类)可以继承父类的方法也可以重写父类的方法。
14、匿名子类(和子类有关的匿名类)的类体中不可以声明static成员变量和static方法。因为无法通过类名来调用静态方法或成员变量。
15、接口匿名类(和接口有关的匿名类)的类体中不可以声明static成员变量和static方法。
16、匿名类一定是内部类。
17、书上的原话是:java使用throw关键字抛出一个Exception子类的实例表示异常发生。
18、一个方法在声明时可以使用throws关键字声明要产生的若干个异常。但是不要在构造方法中抛出异常!
来自百度的解释:
- 我们知道 一个对象的创建,需要经过内存分配,静态代码初始化,构造函数执行等过程,对象生成的关键步骤是构造函数,那是不是允许在构造函数中抛出异常呢?从Java语法上来说,完全可以在构造函数中抛出异常,三类 异常都可以,
但是从系统设计和开发的角度来分析,则尽量不要在构造函数中抛出异常,我们以三种不同类型的异常来说明:
(1)构造函数抛出错误是程序员无法处理的
(2)构造函数不应该抛出非受检查异常
参考来源:
解释链接
解释链接2
19、接口匿名类(和接口有关的匿名类)和匿名子类(子类有关的匿名类)一定不是抽象类。
20、匿名类只有一个不带参数的构造方法(编译器会给匿名类一个名字和构造方法)
21匿名类一定是final类,个人认为原因是不可以被继承,且无类名,无法在其他类中声明对象或调用。
第十二章
1、线程不是进程,但其行为很像进程,线程是比进程更小的执行单位。
2、一个进程在执行过程中,可以产生多个线程,
3、Java应用程序总是从主类的main方法开始执行,JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称为“主线程”(main线程),该线程负责执行main方法。
3、线程在一个完整的生命周期中有一下四种状态:
- 新建
- 运行
- 中断
- 死亡
4、线程调用start方法将启动线程,并不是马上就能运行,而是使之从新建状态进入就绪队列排队,一旦轮到它来享用CPU资源时,就可以脱离创建它的线程独立开始自己的生命周期了。
线程不调用start方法,JVM就仅仅把它当做一个普通对象而不是线程对待。
5、currentThread()方法是Thread类中的static方法,该方法返回当前正在使用CPU资源的线程。
6、线程调用interrupt()方法将使得处于sleep方法或wait方法中断的线程触发InterruptedException异常。
7、wait()、notify()和notifyAll()都是Object类中的final方法,被所有的类继承、且不允许重写,必须在synchronized方法中使用。
8、一个因执行wait方法进入中断状态的线程,需要其他线程执行notify()或notifyAll()通知它结束中断状态。
9、线程在执行完run方法之前,如果再次让线程执行start方法,就会发生ILLegalStateException异常。
10、javax.swing.Timer类称为计时器线程,计时器的监视器必须是组件类的子类的实例,否则计时器无法启动。
11、线程默认是非守护线程(也叫用户线程),当程序中的所有非守护线程都已经结束运行时,即使守护线程的run方法中还有需要执行的语句,守护线程也立刻结束运行。
- 一个线程必须在运行之前设置自己是否是守护线程。
- 一个线程调用setDaemon(boolean on)方法可以将自己设置成一个守护(Daemon)线程。
例如
thread.setDaemon(true);
12、java中的线程可以共享数据。
13、一个线程调用synchronized方法期间,执行sleep方法进入中断后,其他线程也不能调用这个synchronized方法。
14、默认情况下,所有线程的优先级都是5级。
15、run()方法是Runnable接口中的方法。
16、一个线程A在占用CPU资源期间,可以让其他线程调用join()和本线程联合,例如
B.join();
称A在运行期间联合了B。
如果线程A在占用CPU资源期间一旦联合B线程,那么A线程将立刻中断执行,一直等到它联合的线程B执行完毕,A线程再重新排队等待CPU资源,以便回复执行。
如果A准备联合的B线程已经结束,那么B调用join()不会产生任何效果。
第十五章
1、使用List泛型类声明、创建链表时,必须要指定E的具体类型,若想使用多种类型的列表可以用Object类型。
2、链表对象可以使用Iterator()方法获取一个Iterator对象。
3、ArrayList使用顺序结构,LinkedList使用链式结构。
创建
ArrayList<泛型> list=new ArrayList<>();//创建ArrayList
LinkedList<泛型> linklist = new LinkedList<>();//创建LinkedList
4、LinkedList、Stack、ArrayList都实现了List接口。
常用方法
add():添加元素
List<String> list = new ArrayList<>();//创建字符串列表,若是没有明确指定类型时默认为Object
list.add("one");//直接添加元素
list.add(0,"2");//指定索引位置,添加元素
List list1 = new LinkedList();
list1.add("one");//直接添加元素
list1.add(0,1);//指定索引位置,添加元素
Collections.addAll(集合,元素,元素,…);一次添加多个元素
Collections.addAll(list1,"3","4","5");
Collections.addAll(list,"3","4","5");
get():获取元素
List list = new ArrayList<>();//没有指定泛型,则默认为Object
list.add("one");
list.add(0,2);
System.out.println(list.get(1));//字符串 one
System.out.println(list.get(0));//整形 2
List list1 = new LinkedList();
list1.add("one");
list1.add(0,1);
System.out.println(list1.get(1));//字符串 one
System.out.println(list1.get(0));//整形 1
size():获取集合元素的个数
list.size();
contains():判断集合是否含有指定元素,返回Boolean值
list.contains("one");
remove():
list.remove(1);//删除指定下标的元素
list.remove("one");//删除指定元素
clear():清空集合
list.clear();
5、Iterator接口中定义了三种方法
- hasNext():如果仍有元素可以迭代,则返回true。
- next():返回迭代的下一个元素。
- remove():从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作)。
6、HashMap使用方法、
反射
1、获取class对象的方法是:
- 实例对象的getClass方法(实例对象.getClass() ):getClass()方法在object类中定义。
多用于对象的获取字节码的方式。 - 类的class属性(类.class):通过类名的属性class获取
多用于参数的传递 - 类的forName方法(类.forName(“全类名”)):将字节码文件加载进内存,返回Class对象
多用于配置文件,将类名定义在配置文件中。读取文件,加载类。
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
public class Main{
public static void main(String args[]) throws ClassNotFoundException {
//1.Class.forName("全类名")
Class cls1 = Class.forName("daily.People");
System.out.println(cls1);
//2.People class
Class cls2 = People.class;
System.out.println(cls2);
//3.对象.getClass()
People p = new People();
Class cls3 = p.getClass();
System.out.println(cls3);
//== 比较三个对象
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
}
}
2、与java反射相关的类
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Classs类 | |
Class代表类的实体,在运行的java应用程序中表示类和接口。在这个类中提供了很多有用的方法 | |
1、获得类相关方法: |
- getName(): 获取类的完整路径名字。
- newInstance(): 创建类的实例
- getClasses():返回一个包含该类中所有公共类和接口类的对象的数组。
- getDeclaredClasses():返回一个包含该类中所有类和接口类的对象的数组。
- getSuperclass():获得当前类继承的父类的名字。
- getInterfaces():获得当前类实现的类或是接口。-
2、获得类中属性的相关方法
- getField(String name):获得某个公有的属性对象
- getFields():获得所有公有的属性对象
- getDeclaredField(String name):获得某个属性对象。
- getDeclaredFields():获得所有属性对象。
反射Class对象获取成员变量。
import java.lang.reflect.Field;
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/
public class Main{
public static void main(String args[]) throws NoSuchFieldException, IllegalAccessException {
Class peopleClass = People.class;
//1.Field[] getField() 获取所有public修饰的成员变量
Field[] fields = peopleClass.getFields();
for (Field field:fields) {
System.out.println(field);
}
System.out.println("----------------");
Field a = peopleClass.getField("a");
//获取成员变量a的值
People p = new People();
Object value = a.get(p);
System.out.println(value);
//设置a值
a.set(p, "张三");
System.out.println(p);
System.out.println("----------------");
//Field[] getDeclaredFields(),获取所有的成员变量,不考虑修饰符
Field[] declaredFields = peopleClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//Field getDeclaredField(String name)
Field d = peopleClass.getDeclaredField("d");
//忽略访问权限修饰符的安全检查
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
System.out.println(value2);
}
}
public class People{
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public People(){
}
public People(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
}
3、获取类中的构造器只需要把2、中的函数名里面的Field替换成Constructor即可。
- 获取构造方法
package daily;
import java.lang.reflect.Constructor;
/*
* 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
*
* 1.获取构造方法:
* 1).批量的方法:
* public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
* 2).获取单个的方法,并调用:
* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
* 调用构造方法:
* Constructor-->newInstance(Object... initargs)
*/
public class Constructors {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("daily.Student");
System.out.println("******************************所有公有构造方法*********************8");
Constructor[] conArray =clazz.getConstructors();
for (Constructor c : conArray) {
System.out.println(c);
}
System.out.println("****************************所有的构造方法(包括:私有,受保护,默认,公有)**************");
conArray = clazz.getDeclaredConstructors();
for (Constructor c :conArray){
System.out.println(c);
}
System.out.println("*************************获取公有、无参的构造方法**************");
Constructor con = clazz.getConstructor(null);
//1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
//2>、返回的是描述这个无参构造函数的类对象。
Constructor con1 = clazz.getConstructor();
//con和con1是等价的
System.out.println("con= "+con);
System.out.println("con1= "+con1);
//调用构造方法
Object obj = con.newInstance();
// System.out.println("obj = "+ obj);
// Student stu = (Student) obj;
System.out.println("*********************获取私有构造方法,并调用********************");
con = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(con);
//调用构造方法
con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
obj = con.newInstance("刘航航\t",20);
}
}
public class Student {
Student(String str){
System.out.println("(默认)的构造方法:"+str);
}
public Student(){
System.out.println("调用了公有、无参构造方法。。。");
}
public Student(char name){
System.out.println("姓名:"+name);
}
public Student(String name ,int age){
System.out.println("姓名:"+name+"年龄:"+age);
}
protected Student(boolean n){
System.out.println("受保护的构造方法 n = "+ n);
}
private Student(int age){
System.out.println("私有构造方法 年龄"+age);
}
}
4、获取类中相关方法,把2、中的函数名里面的Field替换成Method。
Field代表类的成员变量(成员变量也叫类的属性)
- equals(Object obj)属性与obj相等则返回true
- set(Object obj,Object value) :设置obj中对应属性的值
- get(Object obj):获取obj中对应的属性值
Method代表类的方法
- invoke(Object obj, Object … args):传递obj对象及参数调用该对象对应的方法
- Constructor代表类的构造方法
- newInstance(Object … initargs):根据传递的参数创建类的对象
获取成员方法
package daily;
public class Student {
//************成员方法*****************//
public void show1(String s){
System.out.println("调用了:公有的,String参数的show1():s = "+s);
}
protected void show2(){
System.out.println("调用了:受保护的,无参的show2()");
}
void show3(){
System.out.println("调用了:默认的,无参的show3()");
}
private String show4(int age){
System.out.println("调用了,私有的,并且有返回值的,int参数的show4():age = "+ age);
return "abcd";
}
}
import java.lang.reflect.Method;
/*
* 获取成员方法并调用:
*
* 1.批量的:
* public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
* 2.获取单个的:
* public Method getMethod(String name,Class<?>... parameterTypes):
* 参数:
* name : 方法名;
* Class ... : 形参的Class类型对象
* public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
*
* 调用方法:
* Method --> public Object invoke(Object obj,Object... args):
* 参数说明:
* obj : 要调用方法的对象;
* args:调用方式时所传递的实参;
*/
public class MethodClass {
public static void main(String[] args) throws Exception {
//1.获取class对象
Class stuClass = Class.forName("daily.Student");
//2.获取所有公有方法
System.out.println("********获取所有公有方法**************");
Method[] methodArray = stuClass.getMethods();
for (Method m : methodArray) {
System.out.println(m);
}
System.out.println("*******************获取所有的方法包括私有的**************");
methodArray = stuClass.getDeclaredMethods();
for (Method m : methodArray) {
System.out.println(m);
}
System.out.println("**********************获取公有的show1()方法");
Method m = stuClass.getMethod("show1", String.class);
System.out.println(m);
//实例化一个student对象
Object obj = stuClass.getConstructor().newInstance();
m.invoke(obj,"梁尚福");
System.out.println("*************************获取私有的show4()方法*********************");
m = stuClass.getDeclaredMethod("show4",int.class);
System.out.println(m);
m.setAccessible(true);//暴力反射,解除私有限定
Object result = m.invoke(obj, 20); // 需要两个参数,一个是要调用的对象(获取反射),一个是实参
System.out.println("返回值:"+result);
}
}
注解
1、注解中的变量都是成员变量(属性),并且注解是没有方法的,只有成员变量,变量名就是使用注解括号中对应的参数名,变量返回值是注解括号中对应参数类型。
2、注解的本质就是一个继承了Annotation接口的接口。
3、元注解是用于修饰注解的注解,通常用在注解的定义上。
4、@Target:注解的作用目标,@Retention:注解的生命周期。
- @Targe的ElementType是一个枚举类型
ElemenType.TYPE:允许被修饰的注解作用在类,接口和枚举上。
ElemenType.METHOD:允许作用在方法上。
ElemenType.FIELD:允许作用在属性字段上。 - @Rentention的RententionPolicy是一个枚举类型
RententionPolicy.SOURCE:当前注解编译器可见,仅存在于源码中,不会写入class文件。
RententionPolicy.CLASS:类加载阶段丢弃,运行时无法获得,会写入class文件。
RententionPolicy.RUNTIME:永久保存,可以反射获取。
5、JAVA的内置三大注解
@Override
@Deprecated
@SuppressWarnings
自定义一个注解AnnotationTest,设置参数的默认值为空字符串,年龄默认18
@Target({TYPE, METHOD})
@Retention(RetentionPolicy.RUNTIME )
public @interface AnnotationTest{
String value() default "";
int age() default 18;
}
解析注解
定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 描述需要执行的类名,和方法名称
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface pro {
String ClassName();
String methodName();
}
测试类
package demo;//不在这个包下时该语句可以去掉
import java.lang.reflect.Method;
/**
* 框架类
*/
@pro(ClassName = "demo.ten", methodName = "show")
public class demo10 {
public static void main(String [] args) throws Exception{
/*
*不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
*/
//1解析注解
//1.1获取该类的字节码文件对象
Class<demo10> demo10Class = demo10.class;
//2.获取上边的注解对象
//其实就是在内存中生产了一个该注解接口的子类实现对象
pro an = demo10Class.getAnnotation(pro.class);
//3.调用注解对象中定义的抽象方法,获取返回值
String className = an.ClassName();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);
//加载该类进内存
Class cls = Class.forName(className);
//创建对象
Object obj = cls.newInstance();
//获取方法对象
Method method = cls.getMethod(methodName);
//执行方法
method.invoke(obj);
}
}
class ten {
public void show(){
System.out.println("ten...show...");
}
}
考试注意
- 看清题目!看清题目!看清题目!注意各种情况,要能够处理各种符合要求的数据
- 拿到题目不要急着写,先把思路理清楚,找bug是最费时间的!
- 每一句代码后面都要看有没有分号结尾
- 上转型对象一定要特别注意!尤其是子类添加的新方法和成员变量是无法被父类实例化的对象调用的,上转型对象要是想调用子类新增方法和变量必须强行转换成子类对象!
更多推荐
Java基础知识总结——java快速入门
发布评论