第二周问题

1.为什么return和finally中的改变对象和基本类型的值,值变化不一样?

return之前会先执行finally里的代码,对于非对象类型,finally里的代码不能通过重新给变量赋值来改变return语句的返回值,对于对象类型,和其不同,一个为复制,一个为引用。
也就是说,在进入finally之前,return已经将值压栈,而finally對值进行改变,并不影响值得返回,而对于引用就不一样了,压栈的是引用,返回的也是引用。
如果return是写在finally的话,就好办了,在finally对值进行改变,然后返回,退出程序。

    public Person get(){
    	//int i = 0;
        Person p = new Person("222");
        System.out.println(p.name);
        try{
            return p;
        }catch (Exception e){
            return p;
        }finally {
            p.name = "555";
            p = new Person("111");//和基本类型一样不变 试图改变引用
        }  
    }

2.异常丢失场景

public class Question2 {
	    public static void f1(){
	    	//第一种情况
	    	try {
				try {
					throw new AException("抛出A异常");//丢失A异常
				} finally {
					throw new BException("抛出B异常");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	    }
	
	    
	    public static void f2(){
	    	//第二种情况
	    	try {
	    		throw new AException("抛出A异常");//丢失A异常
			} finally{
				return;
			}
	    }
		public static void main(String[] args) {
			f2();
		}
}

class AException extends Exception{
	public AException(String msg){
		super(msg);
	}
}

class BException extends Exception{
	public BException(String msg){
		super(msg);
	}
}

3.String和Stringbuilder场景 优势

String:String是引用类型,如果我们创建很多个相同值的字符串对象,它在内存中的指向地址应该是一样的。也就是说,当我们创建了字符串对象s,它的值是”1234”,当我们再创建一个值为”1234”的字符串对象str时它不会再去分配一块内存空间,而是直接指向了s在内存中的地址。这样可以确保内存的有效利用。String类型在做字符串的连接操作时,效率是相当低的,并且由于每做一个连接操作,都会在内存中创建一个新的对象,占用了大量的内存空间。
StringBuilder:这样就引出StringBuilder对象,StringBuilder对象在做字符串连接操作时是在原来的字符串上进行修改,改善了性能。这一点我们平时使用中也许都知道,连接操作频繁的时候建议使用StringBuilder对象,如SQL语句的拼装、JSON封装等。
总结:String来做字符串的连接时效率非常低,但并不是所任何情况下都要用StringBuilder,当我们连接很少的字符串时可以用String,但当做大量的或频繁的字符串连接操作时,就一定要用StringBuilder。

4.String a = “1”; String b = “1”; String c = new String(“1”); 是否相等 为什么相等 怎么能相等

参考笔记
string a = “1”;string b = “1”;是存储在方法区中的常量池中的,a、b指向同一个常量池的地址
String c = new String(“1”)方式的声明很明显是正常的创建一个对象的使用方法,所以存储在堆中。

String a = "1";//放在方法区的常量池中
			String b = "1";
			String c = new String("1");//位于堆中
			System.out.println("a==b:"+ (a==b));//true
			System.out.println("a==c:"+ (a==c));//false
			System.out.println("a.equals(b):"+a.equals(b));//true
			System.out.println("a.equals(c):"+a.equals(c));//true

5.类、java 文件(.java文件) 、与字节码文件(.class文件)、类对象、实例之间有什么关系

.java为Java的源文件后缀,编写的代码需要写在.java文件中。
而.class是字节码文件,是.java源文件通过javac命令编译后生成的文件。
Java虚拟机就是去运行.class文件从而实现程序的运行。
类是对事物的描述,而实例化就相当于为这个描述新开辟了一块内存,可以改变这块区域里的各种属性(成员变量)
在java里,Class是一个实实在在的类,在包 java.lang 下,有这样一个Class.java文件,它跟我们自己定义的类一样,是一个实实在在的类,Class对象(类对象)就是这个Class类的实例了。在Java里,所有的类的根源都是Object类,而Class也不例外,它是继承自Object的一个特殊的类,它内部可以记录类的成员、接口等信息,也就是在Java里,Class是一个用来表示类的类。(o(∩_∩)o 有点绕啊,抓住关键一点,Class是一个实实在在的类,可以为它创建实例,也就是本文后面提到的Class对象,也看叫做Class实例)。

java提供了下面几种获取到类的Class对象的方法:

1) 利用对象实例调用getClass()方法获取该对象的Class实例;
   2) 使用Class类的静态方法forName(“全类名”),用类的名字获取一个Class实例,会触发类的初始化
   3)运用 类名.class 的方式来获取Class实例;

   

6.新的转型语法

cast()方法

public static void main(String[] args) {
		Father f = new Son();
		Class<Son> sonType = Son.class;
		Son son = sonType.cast(f);
		son.sonSay();
		//Son s = (Son)f;
		//s.sonSay(); 与cast方法效果一样
	}

7.反射可以修改修饰符吗 实例

访问私有类型时,需要设置值为true,指示反射的对象在使用时应该取消Java语言访问检查
setAccessible(true);

public class Question7 {
		public static void main(String[] args) throws Exception {
			Class<Reflect> classInfo = Reflect.class;
			//获得类的构造参数
			System.out.println("类Reflect构造函数如下所示");
			Constructor cons[] = classInfo.getConstructors();
			for (int i = 0; i < cons.length; i++) {
				System.out.println(cons[i]);
			}
			//获得类的属性
			System.out.println("类Reflect属性如下所示");
			Field[] fields = classInfo.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				System.out.println(fields[i]);
			}
			//获得类的方法
			System.out.println("类Reflect方法如下所示");
			Method[] methods = classInfo.getDeclaredMethods();
			for (int i = 0; i < methods.length; i++) {
				System.out.println(methods[i]);
				
			}
			
			System.out.println("---------------------------------------------");
			Reflect r = new Reflect();
			Field field = r.getClass().getDeclaredField("name");
			field.setAccessible(true); //注意私有类型访问权限需设置为true
			System.out.println(field);
			Object object = field.get(r);
			System.out.println(object);
			field.set(r,"修改私有属性");
			object = field.get(r);
			System.out.println(object);
			System.out.println("---------------------------------------------");
			Method privateMethod = classInfo.getDeclaredMethod("f1");
			//设置对私有方法的访问权限
			privateMethod.setAccessible(true);
	        //执行方法
			privateMethod.invoke(r);
			System.out.println("---------------------------------------------");
			Constructor<Reflect> privateConstructor = classInfo.getConstructor(String.class);
			Reflect newInstance = privateConstructor.newInstance("sss");
			newInstance.f2();
		}
}

class Reflect{
	private String name = "私有属性";
	private int age = 18;
	public Reflect() {
		System.out.println("公共构造器");
	}
	public Reflect(String s) {
		System.out.println("公共构造器");
	}
	private Reflect(int i) {
		System.out.println("私有构造器");
	}
	private void f1() {
		System.out.println("私有方法");
	}
	public void f2() {
		System.out.println("公有方法");
	}
}

8.动态代理 例子

参考
参考2

9.泛型接口实例

泛型类 用于做IPerson接口实现类的的对象操作

接口 interface IPerson{}

实现类1 class Person1 implements IPerson{}

实现类2 class Person2 implements IPerson{}

public class Question9 {
	public static void main(String[] args) {
		IPerson<Integer> person1 = new Person1();
		person1.say(1888);
		IPerson person2 = new Person2();
		person2.say("hello");
	}
}

interface IPerson<T>{
	void say(T t);
}

//第一种在实现接口的子类依旧使用泛型,在实例化的时候在动态添加type
class Person1<T> implements IPerson<T>{

	@Override
	public void say(T t) {
			System.out.println("Person1==>"+t);
	}
	
}

//第二种形式,子类实现接口的时候具体化type,在实例化的时候不用再动态添加type
class Person2 implements IPerson<String>{

	@Override
	public void say(String s) {
				System.out.println("Person2==》"+s);
	}
	
}

10.泛型作用在哪一步 运行时还起作用吗?

Java泛型的实现采取了“伪泛型”的策略,即Java在语法上支持泛型,但是在编译阶段会进行所谓的“类型擦除”(Type Erasure),将所有的泛型表示(尖括号中的内容)都替换为具体的类型(其对应的原生态类型),就像完全没有泛型一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值