java反射空指针(java如何避免空指针异常)

今天给各位分享java反射指针的知识,其中也会对java如何避免空指针异常进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

1、JAVA为什么会空指针异常2、java中的空指针异常怎么解决3、关于java反射调用问题求助!!!4、急:java里造成空指针异常原因有哪些?

JAVA为什么会空指针异常

1.所谓的指针,就是java中的对象的引用。比如String s;这个s就是指针。2.所谓的空指针,就是指针的内容为空,比如上面的s,如果令它指向null,就是空指针。3.所谓的空指针异常,就是一个指针是空指针,你还要去操作它,既然它指向的是空对象,它就不能使用这个对象的方法。比如上面的s假如为null,你还要用s的方法,比如s.equals( String x);那么就会产生空指针异常。

java反射空指针(java如何避免空指针异常)

java中的空指针异常怎么解决

原文:

你这个问题的解决

问题定位:

在堆栈异常信息的第一行就可以定位到是哪里出了空指针,倘若这里不是你写的类,可以往下翻一下,找到你写的类,就是这里出现的空指针。

问题解决:

对一个空对象调用里面的方法或者属性的时候会报空指针,检查这个对象为什么是空即可。

Java 空指针异常的若干解决方案

Java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常,这是一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。本文将列举这些解决方案,包括传统的空值检测、编程规范、以及使用现代 Java 语言引入的各类工具来作为辅助。

运行时检测

最显而易见的方法就是使用 if (obj == null) 来对所有需要用到的对象来进行检测,包括函数参数、返回值、以及类实例的成员变量。当你检测到 null 值时,可以选择抛出更具针对性的异常类型,如 IllegalArgumentException,并添加消息内容。我们可以使用一些库函数来简化代码,如 Java 7 开始提供的 Objects#requireNonNull 方法:

public void testObjects(Object arg) {

Object checked = Objects.requireNonNull(arg, “arg must not be null”);

checked.toString();}

Guava 的 Preconditions 类中也提供了一系列用于检测参数合法性的工具函数,其中就包含空值检测:

public void testGuava(Object arg) {

Object checked = Preconditions.checkNotNull(arg, “%s must not be null”, “arg”);

checked.toString();

}

我们还可以使用 Lombok 来生成空值检测代码,并抛出带有提示信息的空指针异常:

public void testLombok(@NonNull Object arg) {

arg.toString();

生成的代码如下:

public void testLombokGenerated(Object arg) {

if (arg == null) {

throw new NullPointerException(“arg is marked @NonNull but is null”);

}

arg.toString();

}

这个注解还可以用在类实例的成员变量上,所有的赋值操作会自动进行空值检测。

编程规范

·通过遵守某些编程规范,也可以从一定程度上减少空指针异常的发生。

使用那些已经对 null 值做过判断的方法,如 String#equals、String#valueOf、以及三方库中用来判断字符串和集合是否为空的函数:

if (str != null str.equals(“text”)) {}

if (“text”.equals(str)) {}

if (obj != null) { obj.toString(); }

String.valueOf(obj); // “null”

// from spring-core

StringUtils.isEmpty(str);

CollectionUtils.isEmpty(col);

// from guava

Strings.isNullOrEmpty(str);

// from commons-collections4

CollectionUtils.isEmpty(col);

·如果函数的某个参数可以接收 null 值,考虑改写成两个函数,使用不同的函数签名,这样就可以强制要求每个参数都不为空了:

public void methodA(Object arg1) {

methodB(arg1, new Object[0]);

}

public void methodB(Object arg1, Object[] arg2) {

for (Object obj : arg2) {} // no null check

}

·如果函数的返回值是集合类型,当结果为空时,不要返回 null 值,而是返回一个空的集合;如果返回值类型是对象,则可以选择抛出异常。Spring JdbcTemplate 正是使用了这种处理方式:

// 当查询结果为空时,返回 new ArrayList()

jdbcTemplate.queryForList(“SELECT * FROM person”);

// 若找不到该条记录,则抛出 EmptyResultDataAccessException

jdbcTemplate.queryForObject(“SELECT age FROM person WHERE id = 1”, Integer.class);

// 支持泛型集合

public T ListT testReturnCollection() {

return Collections.emptyList();

}

静态代码分析

Java 语言有许多静态代码分析工具,如 Eclipse IDE、SpotBugs、Checker Framework 等,它们可以帮助程序员检测出编译期的错误。结合 @Nullable 和 @Nonnull 等注解,我们就可以在程序运行之前发现可能抛出空指针异常的代码。

但是,空值检测注解还没有得到标准化。虽然 2006 年 9 月社区提出了 JSR 305 规范,但它长期处于搁置状态。很多第三方库提供了类似的注解,且得到了不同工具的支持,其中使用较多的有:

javax.annotation.Nonnull:由 JSR 305 提出,其参考实现为 com.google.code.findbugs.jsr305;

org.eclipse.jdt.annotation.NonNull:Eclipse IDE 原生支持的空值检测注解;

edu.umd.cs.findbugs.annotations.NonNull:SpotBugs 使用的注解,基于 findbugs.jsr305;

org.springframework.lang.NonNull:Spring Framework 5.0 开始提供;

org.checkerframework.checker.nullness.qual.NonNull:Checker Framework 使用;

android.support.annotation.NonNull:集成在安卓开发工具中;

我建议使用一种跨 IDE 的解决方案,如 SpotBugs 或 Checker Framework,它们都能和 Maven 结合得很好。

SpotBugs 与 @NonNull、@CheckForNull

SpotBugs 是 FindBugs 的后继者。通过在方法的参数和返回值上添加 @NonNull 和 @CheckForNull 注解,SpotBugs 可以帮助我们进行编译期的空值检测。需要注意的是,SpotBugs 不支持 @Nullable 注解,必须用 @CheckForNull 代替。如官方文档中所说,仅当需要覆盖 @ParametersAreNonnullByDefault 时才会用到 @Nullable。

官方文档 中说明了如何将 SpotBugs 应用到 Maven 和 Eclipse 中去。我们还需要将 spotbugs-annotations 加入到项目依赖中,以便使用对应的注解。

dependency

   groupIdcom.github.spotbugs/groupId

   artifactIdspotbugs-annotations/artifactId

   version3.1.7/version

/dependency

以下是对不同使用场景的说明:

@NonNull

private Object returnNonNull() {

 // 错误:returnNonNull() 可能返回空值,但其已声明为 @Nonnull

 return null;

}

@CheckForNull

private Object returnNullable() {

 return null;

}

public void testReturnNullable() {

 Object obj = returnNullable();

 // 错误:方法的返回值可能为空

 System.out.println(obj.toString());

}

private void argumentNonNull(@NonNull Object arg) {

 System.out.println(arg.toString());

}

public void testArgumentNonNull() {

 // 错误:不能将 null 传递给非空参数

 argumentNonNull(null);

}

public void testNullableArgument(@CheckForNull Object arg) {

 // 错误:参数可能为空

 System.out.println(arg.toString());

}

对于 Eclipse 用户,还可以使用 IDE 内置的空值检测工具,只需将默认的注解 org.eclipse.jdt.annotation.Nullable 替换为 SpotBugs 的注解即可:

Checker Framework 与 @NonNull、@Nullable

Checker Framework 能够作为 javac 编译器的插件运行,对代码中的数据类型进行检测,预防各类问题。我们可以参照 官方文档,将 Checker Framework 与 maven-compiler-plugin 结合,之后每次执行 mvn compile 时就会进行检查。Checker Framework 的空值检测程序支持几乎所有的注解,包括 JSR 305、Eclipse、甚至 lombok.NonNull。

import org.checkerframework.checker.nullness.qual.Nullable;

@Nullable

private Object returnNullable() {

 return null;

}

public void testReturnNullable() {

 Object obj = returnNullable();

 // 错误:obj 可能为空

 System.out.println(obj.toString());

}

Checker Framework 默认会将 @NonNull 应用到所有的函数参数和返回值上,因此,即使不添加这个注解,以下程序也是无法编译通过的:

private Object returnNonNull() {

 // 错误:方法声明为 @NonNull,但返回的是 null。

 return null;

}

private void argumentNonNull(Object arg) {

 System.out.println(arg.toString());

}

public void testArgumentNonNull() {

 // 错误:参数声明为 @NonNull,但传入的是 null。

 argumentNonNull(null);

}

Checker Framework 对使用 Spring Framework 5.0 以上的用户非常有用,因为 Spring 提供了内置的空值检测注解,且能够被 Checker Framework 支持。一方面我们无需再引入额外的 Jar 包,更重要的是 Spring Framework 代码本身就使用了这些注解,这样我们在调用它的 API 时就能有效地处理空值了。举例来说,StringUtils 类里可以传入空值的函数、以及会返回空值的函数都添加了 @Nullable 注解,而未添加的方法则继承了整个框架的 @NonNull 注解,因此,下列代码中的空指针异常就可以被 Checker Framework 检测到了:

// 这是 spring-core 中定义的类和方法

public abstract class StringUtils {

 // str 参数继承了全局的 @NonNull 注解

 public static String capitalize(String str) {}

 @Nullable

 public static String getFilename(@Nullable String path) {}

}

// 错误:参数声明为 @NonNull,但传入的是 null。

StringUtils.capitalize(null);

String filename = StringUtils.getFilename(“/path/to/file”);

// 错误:filename 可能为空。

System.out.println(filename.length());

Optional 类型

Java 8 引入了 OptionalT 类型,我们可以用它来对函数的返回值进行包装。这种方式的优点是可以明确定义该方法是有可能返回空值的,因此调用方必须做好相应处理,这样也就不会引发空指针异常。但是,也不可避免地需要编写更多代码,而且会产生很多垃圾对象,增加 GC 的压力,因此在使用时需要酌情考虑。

OptionalString opt;

// 创建

opt = Optional.empty();

opt = Optional.of(“text”);

opt = Optional.ofNullable(null);

// 判断并读取

if (opt.isPresent()) {

 opt.get();

}

// 默认值

opt.orElse(“default”);

opt.orElseGet(() – “default”);

opt.orElseThrow(() – new NullPointerException());

// 相关操作

opt.ifPresent(value – {

 System.out.println(value);

});

opt.filter(value – value.length() 5);

opt.map(value – value.trim());

opt.flatMap(value – {

 String trimmed = value.trim();

 return trimmed.isEmpty() ? Optional.empty() : Optional.of(trimmed);

});

方法的链式调用很容易引发空指针异常,但如果返回值都用 Optional 包装起来,就可以用 flatMap 方法来实现安全的链式调用了:

String zipCode = getUser()

   .flatMap(User::getAddress)

   .flatMap(Address::getZipCode)

   .orElse(“”);

Java 8 Stream API 同样使用了 Optional 作为返回类型:

stringList.stream().findFirst().orElse(“default”);

stringList.stream()

   .max(Comparator.naturalOrder())

   .ifPresent(System.out::println);

此外,Java 8 还针对基础类型提供了单独的 Optional 类,如 OptionalInt、OptionalDouble 等,在性能要求比较高的场景下很适用。

其它 JVM 语言中的空指针异常

Scala 语言中的 Option 类可以对标 Java 8 的 Optional。它有两个子类型,Some 表示有值,None 表示空。

val opt: Option[String] = Some(“text”)

opt.getOrElse(“default”)

除了使用 Option#isEmpty 判断,还可以使用 Scala 的模式匹配:

opt match {

 case Some(text) = println(text)

 case None = println(“default”)

Scala 的集合处理函数库非常强大,Option 则可直接作为集合进行操作,如 filer、map、以及列表解析(for-comprehension):

opt.map(_.trim).filter(_.length 0).map(_.toUpperCase).getOrElse(“DEFAULT”)

val upper = for {

 text – opt

 trimmed – Some(text.trim())

 upper – Some(trimmed) if trimmed.length 0

} yield upper

upper.getOrElse(“DEFAULT”)

Kotlin 使用了另一种方式,用户在定义变量时就需要明确区分 可空和不可空类型。当可空类型被使用时,就必须进行空值检测。

var a: String = “text”

a = null // 错误:无法将 null 赋值给非空 String 类型。

val b: String? = “text”

// 错误:操作可空类型时必须使用安全操作符(?.)或强制忽略(!!.)。

println(b.length)

val l: Int? = b?.length // 安全操作

b!!.length // 强制忽略,可能引发空值异常

Kotlin 的特性之一是与 Java 的可互操作性,但 Kotlin 编译器无法知晓 Java 类型是否为空,这就需要在 Java 代码中使用注解了,而 Kotlin 支持的 注解 也非常广泛。Spring Framework 5.0 起原生支持 Kotlin,其空值检测也是通过注解进行的,使得 Kotlin 可以安全地调用 Spring Framework 的所有 API。

结论

在以上这些方案中,我比较推荐使用注解来预防空指针异常,因为这种方式十分有效,对代码的侵入性也较小。所有的公共 API 都应该使用 @Nullable 和 @NonNull 进行注解,这样就能强制调用方对空指针异常进行预防,让我们的程序更为健壮。

关于java反射调用问题求助!!!

整个反射资料都在这:多研究研究

Reflection是Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说”自审”,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。

Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。

JavaBean 是 reflection 的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过 reflection 动态的载入并取得 Java 组件(类) 的属性。

1. 一个简单的例子

考虑下面这个简单的例子,让我们看看 reflection 是如何工作的。

import java.lang.reflect.*;

public class DumpMethods {

public static void main(String args[]) {

try {

Class c = Class.forName(args[0]);

Method m[] = c.getDeclaredMethods();

for (int i = 0; i m.length; i++)

System.out.println(m[i].toString());

} catch (Throwable e) {

System.err.println(e);

}

}

}

按如下语句执行:

java DumpMethods java.util.Stack

它的结果输出为:

public java.lang.Object java.util.Stack.push(java.lang.Object)

public synchronized java.lang.Object java.util.Stack.pop()

public synchronized java.lang.Object java.util.Stack.peek()

public boolean java.util.Stack.empty()

public synchronized int java.util.Stack.search(java.lang.Object)

这样就列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。

这个程序使用 Class.forName 载入指定的类,然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。

2.开始使用 Reflection

用于 reflection 的类,如 Method,可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中,用 java.lang.Class 类来描述类和接口等。

下面就是获得一个 Class 对象的方法之一:

Class c = Class.forName(”java.lang.String”);

这条语句得到一个 String 类的类对象。还有另一种方法,如下面的语句:

Class c = int.class;

或者

Class c = Integer.TYPE;

它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。

第二步是调用诸如 getDeclaredMethods 的方法,以取得该类中定义的所有方法的列表。

一旦取得这个信息,就可以进行第三步了——使用 reflection API 来操作这些信息,如下面这段代码:

Class c = Class.forName(”java.lang.String”);

Method m[] = c.getDeclaredMethods();

System.out.println(m[0].toString());

它将以文本方式打印出 String 中定义的第一个方法的原型。

在下面的例子中,这三个步骤将为使用 reflection 处理特殊应用程序提供例证。

模拟 instanceof 操作符

得到类信息之后,通常下一个步骤就是解决关于 Class 对象的一些基本的问题。例如,Class.isInstance 方法可以用于模拟 instanceof 操作符:

class A {

}

public class instance1 {

public static void main(String args[]) {

try {

Class cls = Class.forName(“A”);

boolean b1 = cls.isInstance(new Integer(37));

System.out.println(b1);

boolean b2 = cls.isInstance(new A());

System.out.println(b2);

} catch (Throwable e) {

System.err.println(e);

}

}

}

在这个例子中创建了一个 A 类的 Class 对象,然后检查一些对象是否是 A 的实例。Integer(37) 不是,但 new A()是。

3.找出类的方法

找出一个类中定义了些什么方法,这是一个非常有价值也非常基础的 reflection 用法。下面的代码就实现了这一用法:

import java.lang.reflect.*;

public class method1 {

private int f1(Object p, int x) throws NullPointerException {

if (p == null)

throw new NullPointerException();

return x;

}

public static void main(String args[]) {

try {

Class cls = Class.forName(“method1”);

Method methlist[] = cls.getDeclaredMethods();

for (int i = 0; i methlist.length; i++) {

Method m = methlist[i];

System.out.println(“name = ” + m.getName());

System.out.println(“decl class = ” + m.getDeclaringClass());

Class pvec[] = m.getParameterTypes();

for (int j = 0; j pvec.length; j++)

System.out.println(“param #” + j + ” ” + pvec[j]);

Class evec[] = m.getExceptionTypes();

for (int j = 0; j evec.length; j++)

System.out.println(“exc #” + j + ” ” + evec[j]);

System.out.println(“return type = ” + m.getReturnType());

System.out.println(“—–“);

}

} catch (Throwable e) {

System.err.println(e);

}

}

}

这个程序首先取得 method1 类的描述,然后调用 getDeclaredMethods 来获取一系列的 Method 对象,它们分别描述了定义在类中的每一个方法,包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 来代替 getDeclaredMethods,你还能获得继承来的各个方法的信息。

取得了 Method 对象列表之后,要显示这些方法的参数类型、异常类型和返回值类型等就不难了。这些类型是基本类型还是类类型,都可以由描述类的对象按顺序给出。

输出的结果如下:

name = f1

decl class = class method1 param #0 class java.lang.Object

param #1 int

exc #0 class java.lang.NullPointerException

return type = int

—–

name = main

decl class = class method1

param #0 class [Ljava.lang.String;

return type = void

4.获取构造器信息

获取类构造器的用法与上述获取方法的用法类似,如:

import java.lang.reflect.*;

public class constructor1 {

public constructor1() {

}

protected constructor1(int i, double d) {

}

public static void main(String args[]) {

try {

Class cls = Class.forName(“constructor1”);

Constructor ctorlist[] = cls.getDeclaredConstructors();

for (int i = 0; i ctorlist.length; i++) {

Constructor ct = ctorlist[i];

System.out.println(“name = ” + ct.getName());

System.out.println(“decl class = ” + ct.getDeclaringClass());

Class pvec[] = ct.getParameterTypes();

for (int j = 0; j pvec.length; j++)

System.out.println(“param #” + j + ” ” + pvec[j]);

Class evec[] = ct.getExceptionTypes();

for (int j = 0; j evec.length; j++)

System.out.println(“exc #” + j + ” ” + evec[j]);

System.out.println(“—–“);

}

} catch (Throwable e) {

System.err.println(e);

}

}

}

这个例子中没能获得返回类型的相关信息,那是因为构造器没有返回类型。

这个程序运行的结果是:

name = constructor1

decl class = class constructor1

—–

name = constructor1

decl class = class constructor1

param #0 int

param #1 double

5.获取类的字段(域)

找出一个类中定义了哪些数据字段也是可能的,下面的代码就在干这个事情:

import java.lang.reflect.*;

public class field1 {

private double d;

public static final int i = 37;

String s = “testing”; public static void main(String args[]) {

try {

Class cls = Class.forName(“field1”);

Field fieldlist[] = cls.getDeclaredFields();

for (int i = 0; i fieldlist.length; i++) {

Field fld = fieldlist[i];

System.out.println(“name = ” + fld.getName());

System.out.println(“decl class = ” + fld.getDeclaringClass());

System.out.println(“type = ” + fld.getType());

int mod = fld.getModifiers();

System.out.println(“modifiers = ” + Modifier.toString(mod));

System.out.println(“—–“);

}

} catch (Throwable e) {

System.err.println(e);

}

}

}

这个例子和前面那个例子非常相似。例中使用了一个新东西 Modifier,它也是一个 reflection 类,用来描述字段成员的修饰语,如“private int”。这些修饰语自身由整数描述,而且使用 Modifier.toString 来返回以“官方”顺序排列的字符串描述 (如“static”在“final”之前)。这个程序的输出是:

name = d

decl class = class field1

type = double

modifiers = private

—–

name = i

decl class = class field1

type = int

modifiers = public static final

—–

name = s

decl class = class field1

type = class java.lang.String

modifiers =

和获取方法的情况一下,获取字段的时候也可以只取得在当前类中申明了的字段信息 (getDeclaredFields),或者也可以取得父类中定义的字段 (getFields) .

6.根据方法的名称来执行方法

文本到这里,所举的例子无一例外都与如何获取类的信息有关。我们也可以用 reflection 来做一些其它的事情,比如执行一个指定了名称的方法。下面的示例演示了这一操作:

import java.lang.reflect.*;

public class method2 {

public int add(int a, int b) {

return a + b;

}

public static void main(String args[]) {

try {

Class cls = Class.forName(“method2”);

Class partypes[] = new Class[2];

partypes[0] = Integer.TYPE;

partypes[1] = Integer.TYPE;

Method meth = cls.getMethod(“add”, partypes);

method2 methobj = new method2();

Object arglist[] = new Object[2];

arglist[0] = new Integer(37);

arglist[1] = new Integer(47);

Object retobj = meth.invoke(methobj, arglist);

Integer retval = (Integer) retobj;

System.out.println(retval.intValue());

} catch (Throwable e) {

System.err.println(e);

}

}

}

假如一个程序在执行的某处的时候才知道需要执行某个方法,这个方法的名称是在程序的运行过程中指定的 (例如,JavaBean 开发环境中就会做这样的事),那么上面的程序演示了如何做到。

上例中,getMethod用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建了相应的Method 对象之后,在正确的对象实例中执行它。执行该方法的时候,需要提供一个参数列表,这在上例中是分别包装了整数 37 和 47 的两个 Integer 对象。执行方法的返回的同样是一个 Integer 对象,它封装了返回值 84.

7.创建新的对象

对于构造器,则不能像执行方法那样进行,因为执行一个构造器就意味着创建了一个新的对象 (准确的说,创建一个对象的过程包括分配内存和构造对象)。所以,与上例最相似的例子如下:

import java.lang.reflect.*;

public class constructor2 {

public constructor2() {

}

public constructor2(int a, int b) {

System.out.println(“a = ” + a + ” b = ” + b);

}

public static void main(String args[]) {

try {

Class cls = Class.forName(“constructor2”);

Class partypes[] = new Class[2];

partypes[0] = Integer.TYPE;

partypes[1] = Integer.TYPE;

Constructor ct = cls.getConstructor(partypes);

Object arglist[] = new Object[2];

arglist[0] = new Integer(37);

arglist[1] = new Integer(47);

Object retobj = ct.newInstance(arglist);

} catch (Throwable e) {

System.err.println(e);

}

}

}

根据指定的参数类型找到相应的构造函数并执行它,以创建一个新的对象实例。使用这种方法可以在程序运行时动态地创建对象,而不是在编译的时候创建对象,这一点非常有价值。

8.改变字段(域)的值

reflection 的还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它,下面的例子可以说明这一点:

import java.lang.reflect.*;

public class field2 {

public double d;

public static void main(String args[]) {

try {

Class cls = Class.forName(“field2”);

Field fld = cls.getField(“d”);

field2 f2obj = new field2();

System.out.println(“d = ” + f2obj.d);

fld.setDouble(f2obj, 12.34);

System.out.println(“d = ” + f2obj.d);

} catch (Throwable e) {

System.err.println(e);

}

}

}

这个例子中,字段 d 的值被变为了 12.34.

9.使用数组

本文介绍的 reflection 的最后一种用法是创建的操作数组。数组在 Java 语言中是一种特殊的类类型,一个数组的引用可以赋给 Object 引用。观察下面的例子看看数组是怎么工作的:

import java.lang.reflect.*;

public class array1 {

public static void main(String args[]) {

try {

Class cls = Class.forName(“java.lang.String”);

Object arr = Array.newInstance(cls, 10);

Array.set(arr, 5, “this is a test”);

String s = (String) Array.get(arr, 5);

System.out.println(s);

} catch (Throwable e) {

System.err.println(e);

}

}

}

例中创建了 10 个单位长度的 String 数组,为第 5 个位置的字符串赋了值,最后将这个字符串从数组中取得并打印了出来。

下面这段代码提供了一个更复杂的例子:

import java.lang.reflect.*;

public class array2 {

public static void main(String args[]) {

int dims[] = new int[]{5, 10, 15};

Object arr = Array.newInstance(Integer.TYPE, dims);

Object arrobj = Array.get(arr, 3);

Class cls = arrobj.getClass().getComponentType();

System.out.println(cls);

arrobj = Array.get(arrobj, 5);

Array.setInt(arrobj, 10, 37);

int arrcast[][][] = (int[][][]) arr;

System.out.println(arrcast[3][5][10]);

}

}

例中创建了一个 5 x 10 x 15 的整型数组,并为处于 [3][5][10] 的元素赋了值为 37.注意,多维数组实际上就是数组的数组,例如,第一个 Array.get 之后,arrobj 是一个 10 x 15 的数组。进而取得其中的一个元素,即长度为 15 的数组,并使用 Array.setInt 为它的第 10 个元素赋值。

注意创建数组时的类型是动态的,在编译时并不知道其类型。

急:java里造成空指针异常原因有哪些?

某一对象没有被实例化,就拿来使用,如调用此对象的方法,会抛空指针异常。

或是获取从别的对象传过来的对象为空,

我所遇到的空指针异常,多是由此引起。

java反射空指针的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java如何避免空指针异常、java反射空指针的信息别忘了在本站进行查找喔。

本文来自投稿,不代表【】观点,发布者:【

本文地址: ,如若转载,请注明出处!

举报投诉邮箱:253000106@qq.com

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024年4月4日 15:14:39
下一篇 2024年4月4日 15:20:48

相关推荐

  • c语言二维数组的指针,c语言二维数组的指针是什么

    C语言中“二维数组行指针”是什么意思 在C语言中,可以通过定义一个行数组指针,使得这个指针与二维数组名具有同样的性质,实现它们之间可以直接赋值。 数组名就是一个指针常量,它代表数组元素在内存相关信息。C语言 是一门通用计算机编程语言,应用广泛。 a即是它的行指针,a+0表示第0行的地址,a+1表示第1行地址…a[row]+col即列指针,列指针经过一次解引用…

    2024年5月23日
    4700
  • java文件异常处理,java异常处理常见问题

    JAVA语言如何进行异常处理? 1、Java语言提供两种异常处理机制:捕获异常和声明抛弃异常。捕获异常:(1)在Java程序运行过程中系统得到一个异常对象是,它将会沿着方法的调用栈逐层回溯,寻找处理这一异常的代码。 2、你同样可以使用Java7的新功能,以移除重复项。 3、异常处理就是捕捉可能在运行时被抛出的异常事件的一项技术。Java通过try-catch…

    2024年5月23日
    5300
  • 单片机c语言释放指针,单片机指针最常见的两种

    c语言指针指向的局部变量释放? C语言中可以使用free函数释放指针。free函数:原型:void free(void ptr);功能:释放malloc(或calloc、realloc)函数给指针变量分配的动态内存。 函数里面的局部变量只有在函数结束后才会释放。main函数里面的a也是,只有main函数结束也就是程序运行结束才会释放。当你进入processi…

    2024年5月22日
    4800
  • java多线程异常,java多线程synchronized

    Java多线程问题总结? 多线程程序都是并发处理的。如果CPU只有一个,那么并发处理就是顺序执行的,而如果有多个CPU,那么并发处理就可能会并行运行。等待队列 所有实例都拥有一个等待队列,它是在实例的wait方法执行后停止操作的线程队列。 多进程——在操作系统中,能同时运行多个任务(程序)。多线程——在同一应用程序中,有多个顺序流同时执行。 多线程和高并发是…

    2024年5月22日
    4000
  • 关于javamvc异常处理的信息

    Java开发都需要学习什么 1、java开发学什么?一起来了解一下吧。需要学习的技术:微服务技术:微服务架构主要有:Spring Cloud、 Dubbo、 Dubbox等,以 Dubbo占比最高,可达26%。 2、Java开发需要学习以下核心知识:Java基础:了解Java的基本语法、数据类型、控制流程、数组、字符串等基础概念。学习面向对象编程(OOP)的…

    2024年5月22日
    3200
  • java异常继承,java异常继续执行

    java所有的异常类皆继承哪一个类 所有的异常类都是从java.lang.Exception类继承的子类。根据查询相关资料信息显示,.java.lang.Throwable是java.lang.Exception的父类,所有的类都继承了Throwable个类。 个人认为你的答案是错误的,因为.java.lang.throwable是java.lang.exc…

    2024年5月22日
    4300
  • c语言数组与指针应用,c语言数组的指针

    C语言中指针和数组是怎样相互转换的 指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。 (1)指针数组:它实际上是一个数组,数组的每个元素存放的是一个指针类型的元素。 地址是可以用加减运算符的,比如a+1就相当于&amp…

    2024年5月21日
    3800
  • c语言指针变量存放地址,c语言指针变量和普通变量的区别

    C语言中变量的地址是什么类型的? 1、逻辑地址,是操作系统分配给你可执行程序的物理地址空间上映射出来的逻辑地址。一般地逻辑地址和物理地址没有直接的关系,这个转换由操作系统完成并维护,与你的程序无关。 2、C语言中,*表示这是一个指针变量,当你定义了一个int p;之后,是无法再次定义一个int *p;的。例如:int *p1;p1 是一个指向 int 类型数…

    2024年5月21日
    3300
  • c语言定义二维数组指针的指针的指针的指针,c++二维数组指针作为函数参数

    C语言如何定义指针指向字符型二维数组 二维数组就是数组的数组,二维数组即数组的元素是一维数组的数组。那么我们要用指针指向二维数组,就是要定义一个指向数组的指针了。 二维数组也是“数组的数组”所以定义一个指向由m个元素组成的一维数组指针即可指向二维数组的首元素地址。 首先我们打开电脑里的C语言软件,新建一个工程和.c文件,输入头文件和主函数。然后我们输入图示代…

    2024年5月21日
    3300
  • c语言函数名本质是指针,c语言函数名是指针吗

    C语言指针函数和函数指针详细介绍 函数指针是指指向某个具体函数的指针变量,在程序设计时可以用来调用某个特定函数或者做某个函数的参数。 指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针 类型标识符 *函数名(参数表)int *f(x,y);函数指针是指向函数的指针变量,即本质是一个指针变量。 指针函数 的本质是 函数 ,只是他的返回值 …

    2024年5月21日
    4200

发表回复

登录后才能评论



关注微信