什麼是類對象?
- 類的對象:基於某個類new出來的對象,也稱爲實例對象。
- 類對象:類加載的產物,封裝了一個類的所有信息(類名、父類、接口、屬性、方法、構造方法)
public class TestClassObject {
public static void main(String[] args) {
//僞代碼
// Class c = new Class();
// c.packageName = "com.qf.day34.reflects.Student";
// c.className = "Student";
// c.superClass = "java.lang.Object";
// C.fileds = new Filed[] {"String name","int age","String sex"};
// c.methods = new methods[] {"public void study() {}","public void exam() {}","public void work() {}"};
// c.constructors() = new constructors[] {"(){}","(String name){}"};
Student s = new Student();//類的對象,基於模板生成的
System.out.println(s.getClass().toString());
Class c = s.getClass();//類對象,類的對象的模板
c.toString();
}
}
class Student{
String name;
int age;
String sex;
public Student() {}
public Student(String name) {
}
public Student(int age) {}
public void study() {}
public void exam() {}
public void work() {}
}
模板類Class(類似於做月餅的模具,對象是類的實例,類是對象的模板)
獲取類對象的方法
- 通過類的對象,獲取類對象
Student s = new Student();
Class c = s.getClass(); - 通過類名獲取類對象
Class c = 類名.class - 通過靜態方法獲取類對象
Class c = Class.forName(“包名.類名”);
public class TestGetClassObject {
public static void main(String[] args) throws ClassNotFoundException {
//1.通過類的對象,獲取Class對象
Person p = new Person();//類的對象
Class c = p.getClass();//類對象Class對象,保存了Person.class這個文件中類的所有信息
System.out.println(c.getName());
//2.通過類名獲取Class對象
Class c2 = Person.class;//但先有Person再有.class
System.out.println(c2.getName());
//3.通過Class的靜態方法獲得Class對象
Class c3 = Class.forName("com.qf.day34.reflects.Person");// throws ClassNotFoundException
System.out.println(c3.getName());
}
//該方法返回一個類對象(Class對象)
//第一種方式,傳不同類時,需要改Person,頻繁修改。改爲Object
// public static Class getClassObject(Person p) {
// Class c = p.getClass();
// return c;
// }
//
public static Class getClassObject(String className) {
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return c;
}
}
class Person{
}
常見操作
常見方法:
- public String getName()
- public Package getPackage()
- public Class<? super T>getSuperclass()
- public Class<?>[] getInterfaces()
- public Filed[] getFields
- public Methods[] getMethods()
- public Constructor<?>[] getConstructors()
- public T newInstance()
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestClassMethods {
public static void main(String[] args) throws Exception {
//1.獲取類對象
Class c = Class.forName("com.qf.day34.methods.Student");
System.out.println(c.getName());
//獲取指定類型的包
Package pack = c.getPackage();
System.out.println(pack.getName());
//獲得父類的Class對象
Class superClass = c.getSuperclass();
System.out.println(superClass.getName());
//獲得接口的Class對象
Class[] interfaces = c.getInterfaces();
for(Class inter:interfaces) {
System.out.println(inter.getName());
}
//獲取屬性(public)自身+父類的公開屬性
Field[] fields = c.getFields();
for(Field f : fields) {
System.out.println(f.getName());
}
System.out.println("---------------------");
//獲得Class對象的自身所在屬性
Field[] fields2 = c.getDeclaredFields();
for(Field f : fields2) {
System.out.println(f.getName());
}
System.out.println("--------Method-------------");
//獲取方法(自身+父類的所有公開方法)
Method[] methods = c.getMethods();
for(Method m : methods) {
System.out.println(m.getName());
}
System.out.println("--------Methodshelf-------------");
//獲取方法(自身+父類的所有公開方法)
Method[] methods2 = c.getDeclaredMethods();
for(Method m : methods2) {
System.out.println(m.getName()+":"+m.getReturnType());
}
System.out.println("--------constructor-------------");
Constructor[] cs = c.getConstructors();
for(Constructor ct : cs) {
System.out.print(ct.getName()+":");
Class[] parm = ct.getParameterTypes();//獲取構造方法的形參
for(Class p : parm) {
System.out.println(p.getName());
}
}
System.out.println("---------------------");
Object o = c.newInstance();
Student stu = (Student)o;
System.out.println(stu);
}
}
class Person{
public String sex;
public double money;
public void eat() {}
public void sleep() {}
}
class Student extends Person implements Serializable,Runnable,Comparable{
public String name;
public int age;
double score;
public Student() {}
public Student(String name) {
}
public Student(String name,int age) {}
private int aaa() {
return 0;
}
public Student(int age) {}
public void study() {}
public void exam() {}
public void work() {}
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
public class TestNewInstance {
public static void main(String[] args) throws Exception {
// //1.手工new對象
// Teacher t = new Teacher();
// t.name = "aaa";
// System.out.println(t.name);
//2.反射通過類對象創建類的對象
// Class c = Teacher.class;
// Teacher t = (Teacher)c.newInstance();
// t.name = "bbb";
// System.out.println(t.name);
Object o = createObject("com.qf.day34.methods.Teacher");
System.out.println(o);
}
//不直接返回Teacher ,爲普適性
//創建對象:
//工廠,創建對象工廠
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class Teacher{
String name;
String sex;
Integer age;
public Teacher() {
}
public Teacher(String name, String sex, Integer age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
public void study() {
System.out.println("我在學習");
}
public void exam() {
System.out.println("我在考試");
}
public void calc() {
System.out.println("我在計算");
}
}
TestNewInstanceForFiles,案例前需要Files\application.txt創建並添加信息
import java.io.BufferedReader;
import java.io.FileReader;
public class TestNewInstanceForFiles {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("Files\\application.txt");
BufferedReader br = new BufferedReader(fr);
String className = br.readLine();
Object o = createObject(className);
System.out.println(o);
}
//創建對象:
//工廠,創建對象工廠
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class Dog{
}
工廠設計模式
- 開發中有一個非常重要的原則“開閉原則”,對拓展開放、對修改關閉
- 工廠模式主要負責對象創建的問題
- 可通過反射進行工廠模式的設計,完成動態的對象創建
invoke方法,執行某個實例
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;
public class TestInvokeMethod {
public static void main(String[] args)throws Exception{
FileReader fr = new FileReader("Files\\application.txt");
BufferedReader br = new BufferedReader(fr);
String className = br.readLine();
Object o = createObject(className);
Class c = o.getClass();//類對象
Method m = c.getMethod("study", null);
m.invoke(o, null);//通過invoke方法,執行某個實例方法,參數:Object->所需對象,args->調用的方法所需的實參
Method m2 = c.getMethod("study",int.class);
m2.invoke(o, 111); //接收方法返回值,如果是基本類型,則轉換爲包裝
Method m3 = c.getMethod("exam",int.class,double.class,String.class);
m3.invoke(o,2,90,"kunyan");
// Method m4 = c.getMethod("clac", null);error無法獲取私有方法
Method m4 = c.getDeclaredMethod("clac", null);//獲得自身方法,包含私有
//注意:反射是一種Java底層技術,可以取消語言檢查,突破封裝
m4.setAccessible(true);
m4.invoke(o, null);
}
//工廠--->創建對象的
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class Student{
String name;
Integer age;
String sex;
Double score;
public Student() {}
public Student(String name, Integer age, String sex, Double score) {
super();
this.name = name;
this.age = age;
this.sex = sex;
this.score = score;
}
public Student(int age) {}
public void study() {
System.out.println("正在學習。。。。");
}
public int study(int a) {
System.out.println("學習"+a+"小時");
return 0;
}
public void exam(int a, double b ,String s) {
System.out.println(s+"學習了"+a+"小時"+"考了"+b);
}
private void clac() {
System.out.println("計算。。。");
}
}
通用方式:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Method;
public class TestInvokeAnything {
public static void main(String[] args) throws Exception {
//invokeAny() --->執行方法
//對象(Object)、方法名稱(String)、形參(Class)、實參(Object)
// FileReader fr = new FileReader("Files\\application.txt");
// BufferedReader br = new BufferedReader(fr);
// String className = br.readLine();
Object o = createObject("com.qf.day35.reflects.Student");
invokeAny(o,"exam",new Class[] {int.class,double.class,String.class},1,99,"kunyan");
invokeAny(o,"study",null,null);
invokeAny(o,"study",new Class[] {int.class},100);
}
//通用(調用任何一個方法)
public static void invokeAny(Object obj ,String methodName,Class[] types,Object... args)throws Exception {
//使用反射技術執行任何方法
//類對象
Class c = obj.getClass();
//獲得方法的對象Methods
Method m = c.getDeclaredMethod(methodName, types);
//執行方法
m.invoke(obj, args);
}
//工廠--->創建對象的
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
單例設計模式
- 只允許創建一個該類的對象
```java
package com.qf.day35.singletons;
public class Test {
public static void main(String[] args) {
Student stu = Student.getStudent();
Student stu1 = Student.getStudent();
Student stu2 = Student.getStudent();
System.out.println(stu);
System.out.println(stu1);
System.out.println(stu2);
}
}
//只創建了一次對象,一個對象----->只能在一個引用中
class Student{
static int count = 0;
//構造方法私有化
private Student() {}
public static Student getStudent() {
count++;
if(count>1) {
return null;
}else {
return new Student();
}
}
}
- 方式1:餓漢式[類加載時創建,天生線程安全]
- 方式2:懶漢式[使用時創建,線程不安全,加同步]
- 方式3:懶漢式(使用時創建,線程安全)
```java
package com.qf.day35.singletons;
public class TestSingleton {
public static void main(String[] args) {
Singleton s1 =Singleton.getInstance();
// Singleton s2 =Singleton.getInstance();
// Singleton s3 =Singleton.getInstance();
// Singleton.instance=null;加私有,依然不可靠,可以利用setAccessible突破封裝,所以加final
System.out.println(s1);
// System.out.println(s2);
// System.out.println(s3);
//什麼時候創建的?類加載就創建,如果沒有使用的話則浪費空間
//線程安全嗎?天生線程安全,無鎖
Singleton1 s11 =Singleton1.getInstance();
// Singleton1 s12 =Singleton1.getInstance();
// Singleton1 s13 =Singleton1.getInstance();
System.out.println(s11);
// System.out.println(s12);
// System.out.println(s13);
//調用時創建的
//線程不安全,容易創建不同對象,上鎖後安全,但效率低
Singleton2 s23 =Singleton2.getInstance();
System.out.println(s23);
}
}
//餓漢式:天生線程安全,無鎖。類加載時創建,但是不用的時候也被創建了,佔用資源
class Singleton{
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
//懶漢式:使用時創建、天生線程不安全(加同步鎖)
class Singleton1{
private static Singleton1 instance = null;
private Singleton1(){}
public synchronized static Singleton1 getInstance() {
if(instance == null) {
instance = new Singleton1();
}
return instance;
}
}
//懶漢式:使用時創建、天生線程安全
class Singleton2{
private Singleton2() {}
private static class Holder{
static final Singleton2 instance = new Singleton2();
}
public static Singleton2 getInstance() {
return Holder.instance;
}
}