Это происходит из-за того, что неявный фид строки, также известный как символ новой строки \n
, добавляется ко всем пользовательским вводам терминала, поскольку он сообщает потоку начать новую строку. Вы можете смело учитывать это, используя std::getline
при проверке нескольких строк ввода пользователя. Поведение по умолчанию std::getline
будет читать все до и включая символ новой строки \n
из объекта входного потока, который в этом случае является std::cin
.
#include
#include
int main()
{
std::string name;
std::string state;
if (std::getline(std::cin, name) && std::getline(std::cin, state))
{
std::cout << "Your name is " << name << " and you live in " << state;
}
return 0;
}
blockquote >Input: "John" "New Hampshire" Output: "Your name is John and you live in New Hampshire"
Поскольку вопрос Что-то вроде `this.class` вместо` ClassName.class`? помечен как дубликат для этого (что можно утверждать, потому что этот вопрос касается класса, а не класса name), я отправляю ответ здесь:
class MyService {
private static Class thisClass = MyService.class;
// or:
//private static Class thisClass = new Object() { }.getClass().getEnclosingClass();
...
static void startService(Context context) {
Intent i = new Intent(context, thisClass);
context.startService(i);
}
}
Важно определить thisClass
как private, потому что: 1) он не должен наследоваться: производные классы должны либо определять свои собственные thisClass
или создать сообщение об ошибке 2) ссылки из других классов должны выполняться как ClassName.class
, а не ClassName.thisClass
.
При определенном thisClass
доступ к имени класса становится:
thisClass.getName()
Я использовал эти два подхода для сценариев static
и non static
:
Основной класс:
//For non static approach
public AndroidLogger(Object classObject) {
mClassName = classObject.getClass().getSimpleName();
}
//For static approach
public AndroidLogger(String className) {
mClassName = className;
}
Как указать имя класса:
нестационарный способ:
private AndroidLogger mLogger = new AndroidLogger(this);
Статический путь:
private static AndroidLogger mLogger = new AndroidLogger(Myclass.class.getSimpleName());
Итак, у нас есть ситуация, когда нам нужно статически получить объект класса или полное / простое имя класса без явного использования синтаксиса MyClass.class
.
В некоторых случаях это может быть очень удобно, например logger для функций верхнего уровня kotlin (в этом случае kotlin создает статический класс Java, недоступный из кода kotlin).
У нас есть несколько разных вариантов для получения этого info:
new Object(){}.getClass().getEnclosingClass();
, отмеченный Том Хотин - галтика getClassContext()[0].getName();
из SecurityManager
, отмеченный Кристоффер new Throwable().getStackTrace()[0].getClassName();
count ludwig Thread.currentThread().getStackTrace()[1].getClassName();
из Keksi MethodHandles.lookup().lookupClass();
из Rein Я подготовил jmh бенчмарк для всех вариантов и результатов:
# Run complete. Total time: 00:04:18
Benchmark Mode Cnt Score Error Units
StaticClassLookup.MethodHandles_lookup_lookupClass avgt 30 3.630 ± 0.024 ns/op
StaticClassLookup.AnonymousObject_getClass_enclosingClass avgt 30 282.486 ± 1.980 ns/op
StaticClassLookup.SecurityManager_classContext_1 avgt 30 680.385 ± 21.665 ns/op
StaticClassLookup.Thread_currentThread_stackTrace_1_className avgt 30 11179.460 ± 286.293 ns/op
StaticClassLookup.Throwable_stackTrace_0_className avgt 30 10221.209 ± 176.847 ns/op
MethodHandles.lookup().lookupClass();
new Object(){}.getClass().getEnclosingClass();
SecurityManager
- ваш друг (третий вариант). Но вы не можете просто называть getClassContext()
- он защищен в классе SecurityManager
. Вам понадобится вспомогательный класс: // Helper class
public final class CallerClassGetter extends SecurityManager
{
private static final CallerClassGetter INSTANCE = new CallerClassGetter();
private CallerClassGetter() {}
public static Class<?> getCallerClass() {
return INSTANCE.getClassContext()[1];
}
}
// Usage example:
class FooBar
{
static final Logger LOGGER = LoggerFactory.getLogger(CallerClassGetter.getCallerClass())
}
getStackTrace()
из исключения или Thread.currentThread()
. Очень неэффективно и может возвращать только имя класса как String
, а не экземпляр Class<*>
.
Если вы хотите создать экземпляр регистратора для статического kotlin utils (например, я :), вы можете использовать этот помощник:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
// Should be inlined to get an actual class instead of the one where this helper declared
// Will work only since Java 7 and Android API 26!
@Suppress("NOTHING_TO_INLINE")
inline fun loggerFactoryStatic(): Logger
= LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())
Пример использования:
private val LOGGER = loggerFactoryStatic()
/**
* Returns a pseudo-random, uniformly distributed value between the
* given least value (inclusive) and bound (exclusive).
*
* @param min the least value returned
* @param max the upper bound (exclusive)
*
* @return the next value
* @throws IllegalArgumentException if least greater than or equal to bound
* @see java.util.concurrent.ThreadLocalRandom.nextDouble(double, double)
*/
fun Random.nextDouble(min: Double = .0, max: Double = 1.0): Double {
if (min >= max) {
if (min == max) return max
LOGGER.warn("nextDouble: min $min > max $max")
return min
}
return nextDouble() * (max - min) + min
}
Рефакторинг-безопасное, разрезанное и вставное безопасное решение, которое позволяет избежать определения классов ad-hoc ниже.
Напишите статический метод, который восстанавливает имя класса, заставляя включать имя класса в имя метода:
private static String getMyClassName(){
return MyClass.class.getName();
}
, затем напомните его в вашем статическом методе:
public static void myMethod(){
Tracer.debug(getMyClassName(), "message");
}
Рефакторинг безопасности предоставляется, избегая использования строк, разрезание и защита пасты предоставляется, потому что если вы вырезаете и вставляете метод вызова, вы не найдете getMyClassName () в целевом классе «MyClass2», поэтому вам придется переопределять и обновлять его.
Я использую это, чтобы запустить Log4j Logger в верхней части моих классов (или аннотировать).
PRO: Throwable уже загружен, и вы можете сэкономить ресурсы, не используя «IO heavy» SecurityManager.
CON: Вопрос о том, будет ли это работать для всех JVM.
// Log4j . Logger --- Get class name in static context by creating an anonymous Throwable and
// getting the top of its stack-trace.
// NOTE you must use: getClassName() because getClass() just returns StackTraceElement.class
static final Logger logger = Logger.getLogger(new Throwable() .getStackTrace()[0].getClassName());
Thread.getStackTrace()
, вы увидите, что он не делает ничего, кроме return (new Exception()).getStackTrace();
в случае вызова на currentThread()
. Таким образом, решение @count ludwig - это более прямой способ добиться того же.
– T-Bull
16 November 2013 в 15:44
Нарушить SecurityManager
System.getSecurityManager().getClassContext()[0].getName();
Или, если он не установлен, используйте внутренний класс, который его расширяет (пример ниже позорно скопирован из Real's HowTo ):
public static class CurrentClassGetter extends SecurityManager {
public String getClassName() {
return getClassContext()[1].getName();
}
}
Если вы используете отражение, вы можете получить объект Method, а затем:
method.getDeclaringClass().getName()
Чтобы получить сам метод, вы, вероятно, можете использовать:
Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod ("method name", parameterTypes)
Class.forName("class name")
уже дает вам класс. Почему вы хотите получить его с помощью метода?
– Sergey Irisov
14 September 2016 в 07:34
Если вы хотите, чтобы с ним было все имя пакета, вызовите:
String name = MyClass.class.getCanonicalName();
Если вы хотите только последний элемент, вызовите:
String name = MyClass.class.getSimpleName();
Вы можете сделать что-то действительно сладкое, используя JNI следующим образом:
MyObject.java:
public class MyObject
{
static
{
System.loadLibrary( "classname" );
}
public static native String getClassName();
public static void main( String[] args )
{
System.out.println( getClassName() );
}
}
then:
javac MyObject.java
javah -jni MyObject
then:
MyObject.c:
#include "MyObject.h"
JNIEXPORT jstring JNICALL Java_MyObject_getClassName( JNIEnv *env, jclass cls )
{
jclass javaLangClass = (*env)->FindClass( env, "java/lang/Class" );
jmethodID getName = (*env)->GetMethodID( env, javaLangClass, "getName",
"()Ljava/lang/String;" );
return (*env)->CallObjectMethod( env, cls, getName );
}
Затем скомпилируйте C вверх в общую библиотеку с именем libclassname.so
и запустите java!
* chuckle
Java_MyObject_getClassName
имеет встроенное имя. Кстати, это использовать JNI RegisterNatives
. Конечно, вам придется кормить это с помощью JNI FindClass(env, 'com/example/MyObject')
, так что победить там тоже не получится.
– Renate
29 November 2014 в 13:36
private static final String TAG = "MyClass"
или private static final String TAG = MyClass.class.getSimpleName();
. Второй более дружелюбен к переименованию глобального класса с использованием среды IDE.
– Renate
30 June 2016 в 11:30
Мне нужно имя класса в статических методах нескольких классов, поэтому я реализовал JavaUtil Class со следующим методом:
public static String getClassName() {
String className = Thread.currentThread().getStackTrace()[2].getClassName();
int lastIndex = className.lastIndexOf('.');
return className.substring(lastIndex + 1);
}
Надеюсь, что это поможет!
В Java 7+ вы можете сделать это в статическом методе / полях:
MethodHandles.lookup().lookupClass()
Reflection.getCallerClass()
. Но это дает предупреждение о том, чтобы быть в пакетах «солнце». Таким образом, это может быть лучшим решением.
– Foumpie
26 December 2015 в 23:55
Reflection.getCallerClass()
. Это немного сложно для его тривиальной операции, т. Е. Optional<Class<?>> myself = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .walk(s -> s.map(StackWalker.StackFrame::getDeclaringClass) .findFirst());
, но, конечно, это связано с тем, что она будет намного более мощной.
– Holger
7 February 2017 в 14:54
Сделайте то, что говорит инструментарий. Не делайте ничего подобного:
return new Object() { }.getClass().getEnclosingClass();